build_info
{
- standard CXX "c++11";
+ standard CXX "c++14";
};
library "mspgltk"
void Container::add(Widget &wdg)
{
wdg.set_parent(this);
- children.push_back(new Child(*this, &wdg));
+ children.push_back(make_unique<Child>(*this, &wdg));
if(wdg.get_animation_interval())
check_animation_interval();
children_rebuild_needed = true;
void Container::remove(Widget &wdg)
{
- auto i = find_if(children, [&wdg](const Child *c){ return c->widget==&wdg; });
+ auto i = find_if(children, [&wdg](const unique_ptr<Child> &c){ return c->widget==&wdg; });
if(i==children.end())
throw hierarchy_error("widget not in container");
if(&wdg==saved_input_focus)
saved_input_focus = nullptr;
wdg.set_parent(nullptr);
- delete *i;
children.erase(i);
if(wdg.get_animation_interval())
check_animation_interval();
vector<Widget *> Container::get_children() const
{
vector<Widget *> result;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
result.push_back(c->widget);
return result;
}
void Container::raise(Widget &wdg)
{
- auto i = find_if(children, [&wdg](const Child *c){ return c->widget==&wdg; });
+ auto i = find_if(children, [&wdg](const unique_ptr<Child> &c){ return c->widget==&wdg; });
if(i==children.end())
throw hierarchy_error("widget not in container");
- Child *c = *i;
+ unique_ptr<Child> c = move(*i);
children.erase(i);
- children.push_back(c);
+ children.push_back(move(c));
}
void Container::set_pointer_focus(Widget *wdg, bool grab)
void Container::check_animation_interval()
{
Time::TimeDelta shortest;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
const Time::TimeDelta &child_iv = c->widget->get_animation_interval();
if(child_iv && (!shortest || child_iv<shortest))
if(children_rebuild_needed)
{
children_rebuild_needed = false;
- for(Child *c: children)
+ for(const unique_ptr<Child> &c: children)
c->widget->rebuild_hierarchy();
}
}
void Container::animate(const Time::TimeDelta &dt)
{
- for(Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
const Time::TimeDelta &child_iv = c->widget->get_animation_interval();
if(!child_iv)
void Container::on_reparent()
{
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
if(Container *o = dynamic_cast<Container *>(c->widget))
o->on_reparent();
#ifndef MSP_GLTK_CONTAINER_H_
#define MSP_GLTK_CONTAINER_H_
+#include <memory>
#include <stdexcept>
#include <vector>
#include <sigc++/trackable.h>
void rebuild_needed();
};
- std::vector<Child *> children;
+ std::vector<std::unique_ptr<Child>> children;
Widget *click_focus = nullptr;
unsigned click_button = 0;
Widget *pointer_focus = nullptr;
void Dialog::Loader::action_button(const string &n, int c)
{
- RefPtr<Button> btn = new Button();
+ unique_ptr<Button> btn = make_unique<Button>();
load_sub(*btn);
obj.add_button(*btn.get(), c);
last_widget = wdg_map[n] = btn.release();
} };
-Layout::~Layout()
-{
- for(Slot *s: slots)
- delete s;
-}
-
void Layout::set_container(Container &c)
{
if(container)
if(!container)
throw logic_error("!container");
- slots.push_back(new Slot(*this, wdg));
+ slots.emplace_back(make_unique<Slot>(*this, wdg));
update_slot_indices();
if(!arrangement_stack.empty())
arrangement_stack.back()->arrange(wdg);
void Layout::remove_widget(Widget &wdg)
{
- auto i = find_if(slots, [&wdg](Slot *s){ return &s->widget==&wdg; });
+ auto i = find_if(slots, [&wdg](const unique_ptr<Slot> &s){ return &s->widget==&wdg; });
if(i==slots.end())
return;
- for(Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
if(s!=*i)
{
for(auto k=s->constraints.begin(); k!=s->constraints.end(); )
{
- if(k->target==*i)
+ if(k->target==i->get())
k = s->constraints.erase(k);
else
++k;
}
}
- delete *i;
slots.erase(i);
update_slot_indices();
{
n_active_slots = 0;
size_t n_floating = 0;
- for(Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
{
if(s->widget.is_visible() || s->ghost)
{
n_slack_vars[0] = n_floating*2;
n_slack_vars[1] = n_floating*2;
- for(const Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
if(s->index>=0)
{
if(!s->floating)
{
for(unsigned j=0; j<2; ++j)
- if((s->*(pointers[j].packing)).gravity==0)
+ if((s.get()->*(pointers[j].packing)).gravity==0)
n_slack_vars[j] += 2;
}
Layout::Slot &Layout::get_slot_for_widget(Widget &wdg)
{
- auto i = find_if(slots, [&wdg](const Slot *s){ return &s->widget==&wdg; });
+ auto i = find_if(slots, [&wdg](const unique_ptr<Slot> &s){ return &s->widget==&wdg; });
if(i==slots.end())
throw hierarchy_error("widget not in layout");
solve_constraints(HORIZONTAL, UPDATE);
solve_constraints(VERTICAL, UPDATE);
- for(const Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
s->widget.set_geometry(s->geom);
}
LinearProgram linprog(n_active_slots*5+n_slack_vars[dir]+1);
float weight = slots.size()+1;
size_t k = n_active_slots*5;
- for(const Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
{
if(s->index<0)
continue;
else
{
if(!s->floating)
- objective[s->index*5] = (s->*(ptrs.packing)).gravity/weight;
- objective[s->index*5+1] = ((s->*(ptrs.packing)).expand ? weight : -1);
+ objective[s->index*5] = (s.get()->*(ptrs.packing)).gravity/weight;
+ objective[s->index*5+1] = ((s.get()->*(ptrs.packing)).expand ? weight : -1);
}
{
row.back() = geom.*(ptrs.dim)-margin.*(ptrs.high_margin);
}
- if(s->floating || (s->*(ptrs.packing)).gravity==0)
+ if(s->floating || (s.get()->*(ptrs.packing)).gravity==0)
{
/* Try to keep the widget as close to a target position as possible.
Since linear programs can't express absolute values directly, use two
opposing slack variables that are optimized for a low value. */
- float a = (s->*(ptrs.packing)).gravity*0.5+0.5;
+ float a = (s.get()->*(ptrs.packing)).gravity*0.5+0.5;
LinearProgram::Row row = linprog.add_row();
row[s->index*5] = 1;
row[s->index*5+1] = a;
if(mode==AUTOSIZE)
{
autosize_geom.*(ptrs.dim) = 0;
- for(const Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
if(s->index>=0)
{
int high_edge = linprog.get_variable(s->index*5)+linprog.get_variable(s->index*5+1);
}
else
{
- for(Slot *s: slots)
+ for(const unique_ptr<Slot> &s: slots)
if(s->index>=0)
{
s->geom.*(ptrs.pos) = linprog.get_variable(s->index*5);
#ifndef MSP_GLTK_LAYOUT_H_
#define MSP_GLTK_LAYOUT_H_
+#include <memory>
#include <vector>
#include <sigc++/trackable.h>
#include <msp/strings/lexicalcast.h>
struct Pointers;
Container *container = nullptr;
- std::vector<Slot *> slots;
+ std::vector<std::unique_ptr<Slot>> slots;
std::size_t n_active_slots = 0;
std::size_t n_slack_vars[2] = { 0, 0 };
Sides margin{ 8 };
static Pointers pointers[2];
public:
- ~Layout();
-
void set_container(Container &);
void set_margin(const Sides &);
const Sides &get_margin() const { return margin; }
{ }
-List::List():
- List(*new BasicListData<string>)
+List::List(unique_ptr<ListData> d):
+ List(*d)
{
- own_data = true;
+ own_data = move(d);
}
+List::List():
+ List(make_unique<BasicListData<string>>())
+{ }
+
List::List(ListData &d):
data(&d),
- observer(new DataObserver(*this))
+ observer(make_unique<DataObserver>(*this))
{
input_type = INPUT_NAVIGATION;
slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
}
-List::~List()
-{
- delete item_factory;
- delete observer;
- if(own_data)
- delete data;
-}
-
void List::autosize_special(const Part &part, Geometry &ageom) const
{
if(part.get_name()=="items")
if(item_factory)
item_factory->set_data(d);
- delete observer;
- if(own_data)
- delete data;
+ observer.reset();
+ own_data.reset();
data = &d;
- own_data = false;
- observer = new DataObserver(*this);
+ observer = make_unique<DataObserver>(*this);
- for(Item *i: items)
- delete i;
items.clear();
size_t n_items = data->size();
for(size_t i=0; i<n_items; ++i)
- {
- Item *item = create_item(i);
- items.push_back(item);
- }
+ items.emplace_back(create_item(i));
items_changed();
}
mark_rebuild();
}
-List::Item *List::create_item(size_t index)
+unique_ptr<List::Item> List::create_item(size_t index)
{
- Item *item = nullptr;
+ unique_ptr<Item> item;
if(item_factory)
item = item_factory->create_item(index);
else
- item = new BasicItem(data->get_string(index));
+ item = make_unique<BasicItem>(data->get_string(index));
if(index==sel_index)
item->set_active(true);
add(*item);
item->autosize();
- item->signal_autosize_changed.connect(sigc::bind(sigc::mem_fun(this, &List::item_autosize_changed), item));
+ item->signal_autosize_changed.connect(sigc::bind(sigc::mem_fun(this, &List::item_autosize_changed), item.get()));
return item;
}
{
items[sel_index]->set_active(true);
if(state&FOCUS)
- set_input_focus(items[focus_index]);
+ set_input_focus(items[focus_index].get());
signal_item_selected.emit(sel_index);
}
}
void List::set_selected_item(Widget *item)
{
for(size_t i=rows[first_row].first; (i<items.size() && items[i]->is_visible()); ++i)
- if(item==items[i])
+ if(item==items[i].get())
return set_selected_index(i);
}
{
Container::focus_in();
if(focus_index!=INVALID_INDEX && items[focus_index]->is_visible())
- set_input_focus(items[focus_index]);
+ set_input_focus(items[focus_index].get());
else
{
if(sel_index!=INVALID_INDEX && items[sel_index]->is_visible())
{
scroll_to_focus();
if(state&FOCUS)
- set_input_focus(items[focus_index]);
+ set_input_focus(items[focus_index].get());
}
}
adjust_index(list.sel_index, i, 1);
adjust_index(list.focus_index, i, 1);
- Item *item = list.create_item(i);
- list.items.insert(list.items.begin()+i, item);
+ list.items.insert(list.items.begin()+i, list.create_item(i));
list.items_changed();
}
adjust_index(list.sel_index, i, -1);
adjust_index(list.focus_index, i, -1);
- delete list.items[i];
list.items.erase(list.items.begin()+i);
list.items_changed();
{
list.sel_index = INVALID_INDEX;
list.focus_index = INVALID_INDEX;
- for(Item *i: list.items)
- delete i;
list.items.clear();
list.items_changed();
void List::DataObserver::refresh_item(size_t i)
{
- delete list.items[i];
- // Avoid stale pointer while create_item is executing
- list.items[i] = nullptr;
+ // Destroy the old item before calling create_item
+ list.items[i].reset();
list.items[i] = list.create_item(i);
list.items_changed();
}
if(part.get_name()=="children")
{
const Sides &margin = part.get_margin();
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
Geometry cgeom;
c->widget->autosize(cgeom);
{
if(part.get_name()=="children")
{
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
c->widget->render(renderer);
}
}
widths.resize(children.size(), 0);
size_t n = 0;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
Geometry cgeom;
c->widget->autosize(cgeom);
const Sides &margin = part->get_margin();
int x = margin.left;
size_t n = 0;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
c->widget->set_position(x, margin.bottom);
x += widths[n++];
if(!style)
return;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
c->widget->autosize();
vector<unsigned> widths;
List *list = static_cast<List *>(parent);
- for(Item *i: list->items)
- if(i!=this)
- if(MultiColumnItem *mci = dynamic_cast<MultiColumnItem *>(i))
+ for(const unique_ptr<Item> &i: list->items)
+ if(i.get()!=this)
+ if(MultiColumnItem *mci = dynamic_cast<MultiColumnItem *>(i.get()))
mci->check_widths(widths);
vector<unsigned> self_widths(widths);
if(update_all)
{
- for(Item *i: list->items)
- if(MultiColumnItem *mci = dynamic_cast<MultiColumnItem *>(i))
+ for(const unique_ptr<Item> &i: list->items)
+ if(MultiColumnItem *mci = dynamic_cast<MultiColumnItem *>(i.get()))
mci->set_widths(self_widths);
}
#ifndef MSP_GLTK_LIST_H_
#define MSP_GLTK_LIST_H_
+#include <memory>
#include <stdexcept>
#include <typeinfo>
#include <sigc++/signal.h>
virtual ~ItemFactory() = default;
virtual void set_data(const ListData &) = 0;
- virtual Item *create_item(std::size_t) const = 0;
+ virtual std::unique_ptr<Item> create_item(std::size_t) const = 0;
};
template<typename I>
throw incompatible_data(typeid(ValueType));
}
- Item *create_item(std::size_t i) const override
+ std::unique_ptr<Item> create_item(std::size_t i) const override
{
- return new I(data->get(i));
+ return std::make_unique<I>(data->get(i));
}
};
sigc::signal<void> signal_selection_cleared;
private:
+ std::unique_ptr<ListData> own_data;
ListData *data = nullptr;
- bool own_data = false;
- DataObserver *observer = nullptr;
- ItemFactory *item_factory = nullptr;
+ std::unique_ptr<DataObserver> observer = nullptr;
+ std::unique_ptr<ItemFactory> item_factory = nullptr;
ViewMode view_mode = LIST;
std::size_t sel_index = INVALID_INDEX;
std::size_t focus_index = INVALID_INDEX;
int drag_start_y = 0;
VSlider slider;
- std::vector<Item *> items;
+ std::vector<std::unique_ptr<Item>> items;
std::vector<Row> rows;
+ List(std::unique_ptr<ListData>);
public:
List();
List(ListData &);
- virtual ~List();
const char *get_class() const override { return "list"; }
public:
template<typename I>
- void set_item_type()
- {
- ItemFactory *f = new TypedItemFactory<I>(*data);
- delete item_factory;
- item_factory = f;
- }
+ void set_item_type() { item_factory = std::make_unique<TypedItemFactory<I>>(*data); }
private:
- Item *create_item(std::size_t);
+ std::unique_ptr<Item> create_item(std::size_t);
public:
void set_view_mode(ViewMode);
#include <msp/core/algorithm.h>
#include <msp/core/maputils.h>
-#include <msp/core/refptr.h>
#include "button.h"
#include "column.h"
#include "draghandle.h"
input_type = INPUT_NAVIGATION;
}
-Panel::~Panel()
-{
- delete layout;
- layout = nullptr;
-}
-
Layout &Panel::get_or_create_layout()
{
if(!layout)
{
- layout = new Layout;
+ layout = make_unique<Layout>();
layout->set_container(*this);
}
{
if(part.get_name()=="children")
{
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
if(c->widget->is_visible())
c->widget->render(renderer);
}
{
Widget *sibling = nullptr;
int best_score = 0;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
if(c->widget==input_focus || !c->widget->is_focusable())
continue;
template<>
void Panel::Loader::unnamed_child<Panel>()
{
- RefPtr<Panel> pnl = new Panel();
+ unique_ptr<Panel> pnl = make_unique<Panel>();
load_sub(*pnl, wdg_map);
obj.add(*pnl.get());
last_widget = pnl.release();
#ifndef MSP_GLTK_PANEL_H_
#define MSP_GLTK_PANEL_H_
+#include <memory>
#include <msp/core/typeregistry.h>
#include "container.h"
#include "layout.h"
protected:
std::vector<Widget *> nav_order;
- Layout *layout = nullptr;
+ std::unique_ptr<Layout> layout;
static TypeRegistry<Loader::AddChildType, Loader &> widget_registry;
static bool widget_registry_init_done;
public:
Panel();
- virtual ~Panel();
template<typename T>
static void register_child_type(const std::string &);
template<typename T>
void Panel::Loader::unnamed_child()
{
- RefPtr<T> chl = new T();
+ std::unique_ptr<T> chl = std::make_unique<T>();
load_sub(*chl);
obj.add(*chl.get());
last_widget = chl.release();
namespace Msp {
namespace GLtk {
-CachedPart::CachedPart(CachedPart &&other):
- part(other.part),
- texture(other.texture),
- mesh(other.mesh)
-{
- other.mesh = nullptr;
-}
-
-CachedPart &CachedPart::operator=(CachedPart &&other)
-{
- delete mesh;
- part = other.part;
- texture = other.texture;
- mesh = other.mesh;
- other.mesh = nullptr;
- return *this;
-}
-
-CachedPart::~CachedPart()
-{
- delete mesh;
-}
-
-
void PartCache::begin_rebuild()
{
if(rebuilding)
{
current = parts.insert(next, CachedPart());
current->texture = &tex;
- current->mesh = new GL::Mesh((GL::TEXCOORD2, GL::COLOR4,GL::UNSIGNED_BYTE, GL::VERTEX2));
+ current->mesh = make_unique<GL::Mesh>((GL::TEXCOORD2, GL::COLOR4,GL::UNSIGNED_BYTE, GL::VERTEX2));
}
else
current->mesh->clear();
#ifndef MSP_GLTK_PARTCACHE_H_
#define MSP_GLTK_PARTCACHE_H_
+#include <memory>
#include <msp/gl/mesh.h>
#include <msp/gl/texture2d.h>
#include "mspgltk_api.h"
{
const Part *part = nullptr;
const GL::Texture2D *texture = nullptr;
- GL::Mesh *mesh = nullptr;
-
- CachedPart() = default;
- CachedPart(CachedPart &&);
- CachedPart &operator=(CachedPart &&);
- ~CachedPart();
+ std::unique_ptr<GL::Mesh> mesh;
};
class MSPGLTK_API PartCache
Resources::Resources(const FS::Path &fn):
Resources()
{
- dir_src = new DataFile::DirectorySource;
+ dir_src = make_unique<DataFile::DirectorySource>();
dir_src->add_directory(FS::dirname(fn));
add_source(*dir_src);
DataFile::load(*this, fn.str());
}
-Resources::~Resources()
-{
- delete dir_src;
-}
-
const GL::Font &Resources::get_default_font() const
{
if(!default_font)
if(name!="ui.glsl")
return nullptr;
- GL::Module *mod = nullptr;
+ unique_ptr<GL::Module> mod;
if(GL::get_backend_api()==GL::VULKAN)
- mod = new GL::SpirVModule;
+ mod = make_unique<GL::SpirVModule>();
else
- mod = new GL::GlslModule;
+ mod = make_unique<GL::GlslModule>();
mod->set_source("import msp_interface; import common;\n"
"uniform sampler2D ui_tex;\n"
"#pragma MSP stage(fragment)\n"
"void main() { frag_color = texture(ui_tex, texcoord.xy)*color; }\n");
- return mod;
+ return mod.release();
}
GL::Program *Resources::create_program(const string &name)
static const Regex r_name("^(linear|nearest)_clamp.samp$");
if(RegMatch m = r_name.match(name))
{
- GL::Sampler *sampler = new GL::Sampler;
+ unique_ptr<GL::Sampler> sampler = make_unique<GL::Sampler>();
sampler->set_filter(lexical_cast<GL::TextureFilter>(toupper(m.group(1).str)));
sampler->set_wrap(GL::CLAMP_TO_EDGE);
- return sampler;
+ return sampler.release();
}
return nullptr;
{
string ext = FS::extpart(name);
if(ext==".png" || ext==".jpg")
- if(IO::Seekable *io = open_raw(name))
+ if(auto io = unique_ptr<IO::Seekable>(open_raw(name)))
{
Graphics::Image image;
image.load_io(*io);
- delete io;
+ io.reset();
- GL::Texture2D *tex = new GL::Texture2D;
+ unique_ptr<GL::Texture2D> tex = make_unique<GL::Texture2D>();
tex->image(image);
- return tex;
+ return tex.release();
}
return nullptr;
void Resources::Loader::font(const string &name)
{
- RefPtr<GL::Font> fnt = new GL::Font;
+ unique_ptr<GL::Font> fnt = make_unique<GL::Font>();
load_sub(*fnt, res);
res.add(name, fnt.get());
if(!res.default_font)
#ifndef MSP_GLTK_RESOURCES_H_
#define MSP_GLTK_RESOURCES_H_
+#include <memory>
#include <msp/gl/font.h>
#include <msp/gl/module.h>
#include <msp/gl/program.h>
private:
FS::Path path;
GL::Font *default_font = nullptr;
- DataFile::DirectorySource *dir_src = nullptr;
+ std::unique_ptr<DataFile::DirectorySource> dir_src;
public:
Resources();
Resources(const FS::Path &);
- ~Resources();
const GL::Font &get_default_font() const;
const GL::Sampler &get_default_sampler() const;
#include "root.h"
#include "systemkeyboardinput.h"
+using namespace std;
+
namespace Msp {
namespace GLtk {
-Root::Root(Resources &r, Graphics::Window &window):
- Root(r, &window, new Input::Keyboard(window), new Input::Mouse(window), nullptr)
+Root::Root(Resources &r, Graphics::Window &window, unique_ptr<Input::Keyboard> k, unique_ptr<Input::Mouse> m):
+ Root(r, &window, k.get(), m.get(), nullptr)
{
- own_input = true;
+ own_input[0] = move(k);
+ own_input[1] = move(m);
}
+Root::Root(Resources &r, Graphics::Window &window):
+ Root(r, window, make_unique<Input::Keyboard>(window), make_unique<Input::Mouse>(window))
+{ }
+
Root::Root(Resources &r, Graphics::Window *window, Input::Keyboard *k, Input::Mouse *m, Input::Touchscreen *t):
resources(r),
keyboard(k),
}
if(keyboard && !input_method)
- input_method = new SystemKeyboardInput(*this, *keyboard);
+ input_method = make_unique<SystemKeyboardInput>(*this, *keyboard);
if(touchscreen)
{
}
}
-Root::~Root()
-{
- delete input_method;
- if(own_input)
- {
- delete keyboard;
- delete mouse;
- }
-}
-
void Root::tick()
{
Time::TimeStamp t = Time::now();
#ifndef MSP_GLTK_ROOT_H_
#define MSP_GLTK_ROOT_H_
+#include <memory>
#include <sigc++/trackable.h>
#include <msp/gl/blend.h>
#include <msp/gl/camera.h>
private:
Resources &resources;
Input::Keyboard *keyboard = nullptr;
- InputMethod *input_method = nullptr;
+ std::unique_ptr<InputMethod> input_method;
Input::Mouse *mouse = nullptr;
Input::Touchscreen *touchscreen = nullptr;
- bool own_input = false;
+ std::unique_ptr<Input::Device> own_input[2];
Label *lbl_tooltip = nullptr;
int pointer_x = 0;
int pointer_y = 0;
Msp::GL::Program *shprog = nullptr;
Msp::GL::Blend blend;
+ Root(Resources &, Graphics::Window &, std::unique_ptr<Input::Keyboard>, std::unique_ptr<Input::Mouse>);
+
public:
/** Creates a Root widget for a window. The geometry is set to match the
window's size, and input devices are created automatically. */
/** Creates a Root widget with custom input devices. If window is not null,
it is used to set the widget's initial geometry. */
Root(Resources &, Graphics::Window *, Input::Keyboard *, Input::Mouse *, Input::Touchscreen * = nullptr);
- virtual ~Root();
const char *get_class() const override { return "root"; }