summaryrefslogtreecommitdiff
path: root/libs/gtkmm2ext
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2016-05-27 12:58:55 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2016-05-31 15:30:45 -0400
commit067616a84f6ee6be2d2f77877fbf5f8bdc10775a (patch)
tree11528eaea7d62f27d42cf17ff88bd5e8c5f388b2 /libs/gtkmm2ext
parent95be25047c12973ee81260558b4aa1be253956de (diff)
various work on Pane, including cursors, more styling stuff, and making the forall_vfunc safe against gtk_container_remove
Diffstat (limited to 'libs/gtkmm2ext')
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/pane.h13
-rw-r--r--libs/gtkmm2ext/pane.cc110
2 files changed, 91 insertions, 32 deletions
diff --git a/libs/gtkmm2ext/gtkmm2ext/pane.h b/libs/gtkmm2ext/gtkmm2ext/pane.h
index 452c9f9f0a..ecf466833a 100644
--- a/libs/gtkmm2ext/gtkmm2ext/pane.h
+++ b/libs/gtkmm2ext/gtkmm2ext/pane.h
@@ -25,6 +25,7 @@
#include <stdint.h>
+#include <gdkmm/cursor.h>
#include <gtkmm/container.h>
#include <gtkmm/eventbox.h>
@@ -47,8 +48,9 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
float get_divider (std::vector<float>::size_type divider = 0);
GType child_type_vfunc() const;
+ void set_drag_cursor (Gdk::Cursor);
-
+ protected:
bool horizontal;
void on_add (Gtk::Widget*);
@@ -60,10 +62,15 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
bool handle_press_event (GdkEventButton*, Divider*);
bool handle_release_event (GdkEventButton*, Divider*);
bool handle_motion_event (GdkEventMotion*, Divider*);
+ bool handle_enter_event (GdkEventCrossing*, Divider*);
+ bool handle_leave_event (GdkEventCrossing*, Divider*);
void forall_vfunc (gboolean include_internals, GtkCallback callback, gpointer callback_data);
private:
+ Gdk::Cursor drag_cursor;
+ bool did_move;
+
void reallocate (Gtk::Allocation const &);
typedef std::list<Gtk::Widget*> Children;
@@ -76,11 +83,9 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
bool dragging;
bool on_expose_event (GdkEventExpose* ev);
- bool on_enter_notify_event (GdkEventCrossing*);
- bool on_leave_notify_event (GdkEventCrossing*);
};
- typedef std::vector<Divider*> Dividers;
+ typedef std::list<Divider*> Dividers;
Dividers dividers;
int divider_width;
void add_divider ();
diff --git a/libs/gtkmm2ext/pane.cc b/libs/gtkmm2ext/pane.cc
index 2472d0257d..5945ec40dc 100644
--- a/libs/gtkmm2ext/pane.cc
+++ b/libs/gtkmm2ext/pane.cc
@@ -17,6 +17,7 @@
*/
+#include <gdkmm/cursor.h>
#include "gtkmm2ext/pane.h"
#include "i18n.h"
@@ -28,10 +29,25 @@ using namespace std;
Pane::Pane (bool h)
: horizontal (h)
+ , did_move (false)
, divider_width (5)
{
+ using namespace Gdk;
+
set_name ("Pane");
set_has_window (false);
+
+ if (horizontal) {
+ drag_cursor = Cursor (SB_H_DOUBLE_ARROW);
+ } else {
+ drag_cursor = Cursor (SB_H_DOUBLE_ARROW);
+ }
+}
+
+void
+Pane::set_drag_cursor (Gdk::Cursor c)
+{
+ drag_cursor = c;
}
void
@@ -41,11 +57,11 @@ Pane::on_size_request (GtkRequisition* req)
/* iterate over all children, get their size requests */
- /* horizontal pane is as high as its tallest child, but has no width
- * requirement.
+ /* horizontal pane is as high as its tallest child, including the dividers.
+ * Its width is the sum of the children plus the dividers.
*
- * vertical pane is as wide as its widest child, but has no height
- * requirement.
+ * vertical pane is as wide as its widest child, including the dividers.
+ * Its height is the sum of the children plus the dividers.
*/
if (horizontal) {
@@ -76,6 +92,7 @@ Pane::on_size_request (GtkRequisition* req)
GType
Pane::child_type_vfunc() const
{
+ /* We accept any number of any types of widgets */
return Gtk::Widget::get_type();
}
@@ -86,6 +103,8 @@ Pane::add_divider ()
d->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Pane::handle_press_event), d), false);
d->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &Pane::handle_release_event), d), false);
d->signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun (*this, &Pane::handle_motion_event), d), false);
+ d->signal_enter_notify_event().connect (sigc::bind (sigc::mem_fun (*this, &Pane::handle_enter_event), d), false);
+ d->signal_leave_notify_event().connect (sigc::bind (sigc::mem_fun (*this, &Pane::handle_leave_event), d), false);
d->set_parent (*this);
d->show ();
d->fract = 0.5;
@@ -121,7 +140,6 @@ Pane::on_size_allocate (Gtk::Allocation& alloc)
void
Pane::reallocate (Gtk::Allocation const & alloc)
{
- Children::size_type n = 0;
int remaining;
int xpos = alloc.get_x();
int ypos = alloc.get_y();
@@ -132,6 +150,7 @@ Pane::reallocate (Gtk::Allocation const & alloc)
}
if (children.size() == 1) {
+ /* only child gets the full allocation */
children.front()->size_allocate (alloc);
return;
}
@@ -146,7 +165,7 @@ Pane::reallocate (Gtk::Allocation const & alloc)
Children::iterator next;
Dividers::iterator div;
- for (child = children.begin(), div = dividers.begin(); child != children.end(); ++n) {
+ for (child = children.begin(), div = dividers.begin(); child != children.end(); ) {
Gtk::Allocation child_alloc;
next = child;
@@ -155,12 +174,12 @@ Pane::reallocate (Gtk::Allocation const & alloc)
child_alloc.set_x (xpos);
child_alloc.set_y (ypos);
- if (n >= dividers.size()) {
- /* the next child gets all the remaining space */
+ if (next == children.end()) {
+ /* last child gets all the remaining space */
fract = 1.0;
} else {
- /* the next child gets the fraction of the remaining space given by the divider that follows it */
- fract = dividers[n]->fract;
+ /* child gets the fraction of the remaining space given by the divider that follows it */
+ fract = (*div)->fract;
}
Gtk::Requisition cr;
@@ -213,14 +232,15 @@ Pane::reallocate (Gtk::Allocation const & alloc)
bool
Pane::on_expose_event (GdkEventExpose* ev)
{
- Children::size_type n = 0;
+ Children::iterator child;
+ Dividers::iterator div;
- for (Children::iterator child = children.begin(); child != children.end(); ++child, ++n) {
+ for (child = children.begin(), div = dividers.begin(); child != children.end(); ++child, ++div) {
propagate_expose (**child, ev);
- if (n < dividers.size()) {
- propagate_expose (*dividers[n], ev);
+ if (div != dividers.end()) {
+ propagate_expose (**div, ev);
}
}
@@ -240,7 +260,11 @@ bool
Pane::handle_release_event (GdkEventButton* ev, Divider* d)
{
d->dragging = false;
- children.front()->queue_resize ();
+
+ if (did_move) {
+ children.front()->queue_resize ();
+ did_move = false;
+ }
return false;
}
@@ -248,6 +272,8 @@ Pane::handle_release_event (GdkEventButton* ev, Divider* d)
bool
Pane::handle_motion_event (GdkEventMotion* ev, Divider* d)
{
+ did_move = true;
+
if (!d->dragging) {
return true;
}
@@ -305,12 +331,20 @@ Pane::set_divider (Dividers::size_type div, float fract)
{
bool redraw = false;
- while (dividers.size() <= div) {
- add_divider ();
+ Dividers::iterator d = dividers.begin();
+
+ while (div--) {
+ ++d;
+ if (d == dividers.end()) {
+ /* caller is trying to set divider that does not exist
+ * yet.
+ */
+ return;
+ }
}
- if (fract != dividers[div]->fract) {
- dividers[div]->fract = fract;
+ if (fract != (*d)->fract) {
+ (*d)->fract = fract;
redraw = true;
}
@@ -324,23 +358,41 @@ Pane::set_divider (Dividers::size_type div, float fract)
float
Pane::get_divider (Dividers::size_type div)
{
- if (div >= dividers.size()) {
- return -1;
+ Dividers::iterator d = dividers.begin();
+
+ while (div--) {
+ ++d;
+ if (d == dividers.end()) {
+ /* caller is trying to set divider that does not exist
+ * yet.
+ */
+ return -1.0f;
+ }
}
- return dividers[div]->fract;
+ return (*d)->fract;
}
void
Pane::forall_vfunc (gboolean include_internals, GtkCallback callback, gpointer callback_data)
{
- for (Children::iterator w = children.begin(); w != children.end(); ++w) {
+ /* since the callback could modify the child list(s), make sure we keep
+ * the iterators safe;
+ */
+
+ for (Children::iterator w = children.begin(); w != children.end(); ) {
+ Children::iterator next = w;
+ ++next;
callback ((*w)->gobj(), callback_data);
+ w = next;
}
if (include_internals) {
- for (Dividers::iterator d = dividers.begin(); d != dividers.end(); ++d) {
+ for (Dividers::iterator d = dividers.begin(); d != dividers.end(); ) {
+ Dividers::iterator next = d;
+ ++next;
callback (GTK_WIDGET((*d)->gobj()), callback_data);
+ d = next;
}
}
}
@@ -372,15 +424,17 @@ Pane::Divider::on_expose_event (GdkEventExpose* ev)
}
bool
-Pane::Divider::on_enter_notify_event (GdkEventCrossing*)
+Pane::handle_enter_event (GdkEventCrossing*, Divider* d)
{
- set_state (Gtk::STATE_SELECTED);
+ d->get_window()->set_cursor (drag_cursor);
+ d->set_state (Gtk::STATE_SELECTED);
return true;
}
bool
-Pane::Divider::on_leave_notify_event (GdkEventCrossing*)
+Pane::handle_leave_event (GdkEventCrossing*, Divider* d)
{
- set_state (Gtk::STATE_NORMAL);
+ d->get_window()->set_cursor ();
+ d->set_state (Gtk::STATE_NORMAL);
return true;
}