diff --git a/aegisub/build/libaegisub/libaegisub.vcxproj b/aegisub/build/libaegisub/libaegisub.vcxproj
index 9242f69ea..a73a35119 100644
--- a/aegisub/build/libaegisub/libaegisub.vcxproj
+++ b/aegisub/build/libaegisub/libaegisub.vcxproj
@@ -67,6 +67,7 @@
+
diff --git a/aegisub/build/libaegisub/libaegisub.vcxproj.filters b/aegisub/build/libaegisub/libaegisub.vcxproj.filters
index 1c487e2cc..a73b5aaf7 100644
--- a/aegisub/build/libaegisub/libaegisub.vcxproj.filters
+++ b/aegisub/build/libaegisub/libaegisub.vcxproj.filters
@@ -161,6 +161,9 @@
Header Files
+
+ Header Files
+
diff --git a/aegisub/libaegisub/include/libaegisub/owning_intrusive_list.h b/aegisub/libaegisub/include/libaegisub/owning_intrusive_list.h
new file mode 100644
index 000000000..d5b88e1b5
--- /dev/null
+++ b/aegisub/libaegisub/include/libaegisub/owning_intrusive_list.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#pragma once
+
+#include
+
+namespace agi {
+
+template
+class owning_intrusive_list : private boost::intrusive::make_list>::type {
+ typedef typename boost::intrusive::make_list>::type base;
+public:
+ using base::back;
+ using base::begin;
+ using base::cbegin;
+ using base::cend;
+ using base::crbegin;
+ using base::crend;
+ using base::empty;
+ using base::end;
+ using base::front;
+ using base::insert;
+ using base::iterator_to;
+ using base::merge;
+ using base::push_back;
+ using base::push_front;
+ using base::rbegin;
+ using base::rend;
+ using base::reverse;
+ using base::s_iterator_to;
+ using base::shift_backwards;
+ using base::shift_forward;
+ using base::size;
+ using base::sort;
+ using base::splice;
+ using base::swap;
+
+ using typename base::const_node_ptr;
+ using typename base::const_pointer;
+ using typename base::const_reverse_iterator;
+ using typename base::node;
+ using typename base::node_algorithms;
+ using typename base::node_ptr;
+ using typename base::node_traits;
+ using typename base::pointer;
+ using typename base::reference;
+ using typename base::reverse_iterator;
+ using typename base::size_type;
+ using typename base::value_type;
+ using typename base::iterator;
+ using typename base::const_iterator;
+ using typename base::const_reference;
+ using typename base::difference_type;
+
+ iterator erase(const_iterator b, const_iterator e) { return this->erase_and_dispose(b, e, [](T *e) { delete e; }); }
+ iterator erase(const_iterator b, const_iterator e, difference_type n) { return this->erase_and_dispose(b, e, n, [](T *e) { delete e; }); }
+ iterator erase(const_iterator i) { return this->erase_and_dispose(i, [](T *e) { delete e; }); }
+ void clear() { this->clear_and_dispose([](T *e) { delete e; }); }
+ void pop_back() { this->pop_back_and_dispose([](T *e) { delete e; }); }
+ void pop_front() { this->pop_front_and_dispose([](T *e) { delete e; }); }
+ void remove(const_reference value) { return this->remove_and_dispose(value, [](T *e) { delete e; }); }
+ void unique() { this->unique_and_dispose([](T *e) { delete e; }); }
+
+ template void remove_if(Pred&& pred) {
+ this->remove_if_and_dispose(std::forward(pred), [](T *e) { delete e; });
+ }
+
+ template void unique(BinaryPredicate&& pred) {
+ this->unique_and_dispose(std::forward(pred), [](T *e) { delete e; });
+ }
+
+ ~owning_intrusive_list() {
+ clear();
+ }
+};
+
+}
+
diff --git a/aegisub/src/visual_feature.cpp b/aegisub/src/visual_feature.cpp
index 250ba1d61..2a94edd89 100644
--- a/aegisub/src/visual_feature.cpp
+++ b/aegisub/src/visual_feature.cpp
@@ -40,7 +40,7 @@
VisualDraggableFeature::VisualDraggableFeature()
: type(DRAG_NONE)
, layer(0)
-, line(0)
+, line(nullptr)
{
}
diff --git a/aegisub/src/visual_feature.h b/aegisub/src/visual_feature.h
index 425c43f26..ef4c935b5 100644
--- a/aegisub/src/visual_feature.h
+++ b/aegisub/src/visual_feature.h
@@ -36,6 +36,8 @@
#include "vector2d.h"
+#include
+
class OpenGLWrapper;
class AssDialogue;
@@ -54,7 +56,7 @@ enum DraggableFeatureType {
///
/// By itself this class doesn't do much. It mostly just draws itself at a
/// specified position and performs hit-testing.
-class VisualDraggableFeature {
+class VisualDraggableFeature : public boost::intrusive::make_list_base_hook>::type {
Vector2D start; ///< position before the last drag operation began
public:
diff --git a/aegisub/src/visual_tool.cpp b/aegisub/src/visual_tool.cpp
index cec2e15a0..82c87105d 100644
--- a/aegisub/src/visual_tool.cpp
+++ b/aegisub/src/visual_tool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, Thomas Goyne
+// Copyright (c) 2013, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -43,7 +43,12 @@
using std::placeholders::_1;
-const wxColour VisualToolBase::colour[4] = {wxColour(106,32,19), wxColour(255,169,40), wxColour(255,253,185), wxColour(187,0,0)};
+const wxColour VisualToolBase::colour[] = {
+ wxColour(106,32,19),
+ wxColour(255,169,40),
+ wxColour(255,253,185),
+ wxColour(187,0,0)
+};
VisualToolBase::VisualToolBase(VideoDisplay *parent, agi::Context *context)
: c(context)
@@ -165,8 +170,8 @@ template
VisualTool::VisualTool(VideoDisplay *parent, agi::Context *context)
: VisualToolBase(parent, context)
, sel_changed(false)
+, active_feature(nullptr)
{
- active_feature = features.begin();
}
template
@@ -179,30 +184,21 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
mouse_pos = event.GetPosition();
- bool need_render = false;
-
if (event.Leaving()) {
mouse_pos = Vector2D();
parent->Render();
return;
}
- if (event.Entering() && OPT_GET("Tool/Visual/Autohide")->GetBool())
- need_render = true;
-
if (!dragging) {
- feature_iterator prev_feature = active_feature;
-
int max_layer = INT_MIN;
- active_feature = features.end();
- for (feature_iterator cur = features.begin(); cur != features.end(); ++cur) {
- if (cur->IsMouseOver(mouse_pos) && cur->layer >= max_layer) {
- active_feature = cur;
- max_layer = cur->layer;
+ active_feature = nullptr;
+ for (auto& feature : features) {
+ if (feature.IsMouseOver(mouse_pos) && feature.layer >= max_layer) {
+ active_feature = &feature;
+ max_layer = feature.layer;
}
}
-
- need_render |= active_feature != prev_feature;
}
if (dragging) {
@@ -213,14 +209,13 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
for (auto sel : sel_features)
UpdateDrag(sel);
Commit();
- need_render = true;
}
// end drag
else {
dragging = false;
// mouse didn't move, fiddle with selection
- if (active_feature != features.end() && !active_feature->HasMoved()) {
+ if (active_feature && !active_feature->HasMoved()) {
// Don't deselect stuff that was selected in this click's mousedown event
if (!sel_changed) {
if (ctrl_down)
@@ -230,7 +225,7 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
}
}
- active_feature = features.end();
+ active_feature = nullptr;
parent->ReleaseMouse();
parent->SetFocus();
}
@@ -244,7 +239,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
}
UpdateHold();
- need_render = true;
Commit();
}
@@ -252,7 +246,7 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
drag_start = mouse_pos;
// start drag
- if (active_feature != features.end()) {
+ if (active_feature) {
if (!sel_features.count(active_feature)) {
sel_changed = true;
SetSelection(active_feature, !ctrl_down);
@@ -276,7 +270,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
SubtitleSelection sel;
sel.insert(c->selectionController->GetActiveLine());
c->selectionController->SetSelectedSet(sel);
- need_render = true;
}
if (active_line && InitializeHold()) {
holding = true;
@@ -288,8 +281,7 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
if (active_line && left_double)
OnDoubleClick();
- //if (need_render)
- parent->Render();
+ parent->Render();
// Only coalesce the changes made in a single drag
if (!event.LeftIsDown())
@@ -299,19 +291,19 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) {
template
void VisualTool::DrawAllFeatures() {
gl.SetLineColour(colour[0], 1.0f, 2);
- for (feature_iterator cur = features.begin(); cur != features.end(); ++cur) {
+ for (auto& feature : features) {
int fill = 1;
- if (cur == active_feature)
+ if (&feature == active_feature)
fill = 2;
- else if (sel_features.count(cur))
+ else if (sel_features.count(&feature))
fill = 3;
gl.SetFillColour(colour[fill], 0.6f);
- cur->Draw(gl);
+ feature.Draw(gl);
}
}
template
-void VisualTool::SetSelection(feature_iterator feat, bool clear) {
+void VisualTool::SetSelection(FeatureType *feat, bool clear) {
if (clear)
sel_features.clear();
@@ -325,12 +317,10 @@ void VisualTool::SetSelection(feature_iterator feat, bool clear) {
}
template
-void VisualTool::RemoveSelection(feature_iterator feat) {
+void VisualTool::RemoveSelection(FeatureType *feat) {
if (!sel_features.erase(feat) || !feat->line) return;
-
- for (auto sel : sel_features) {
+ for (auto sel : sel_features)
if (sel->line == feat->line) return;
- }
SubtitleSelection sel = c->selectionController->GetSelectedSet();
diff --git a/aegisub/src/visual_tool.h b/aegisub/src/visual_tool.h
index 967fcd51e..4706e5502 100644
--- a/aegisub/src/visual_tool.h
+++ b/aegisub/src/visual_tool.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, Thomas Goyne
+// Copyright (c) 2013, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -20,22 +20,17 @@
#pragma once
-#include
-#include
-#include