mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 04:06:26 +01:00
various work on Pane, including cursors, more styling stuff, and making the forall_vfunc safe against gtk_container_remove
This commit is contained in:
parent
95be25047c
commit
067616a84f
2 changed files with 91 additions and 32 deletions
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <gdkmm/cursor.h>
|
||||||
#include <gtkmm/container.h>
|
#include <gtkmm/container.h>
|
||||||
#include <gtkmm/eventbox.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);
|
float get_divider (std::vector<float>::size_type divider = 0);
|
||||||
|
|
||||||
GType child_type_vfunc() const;
|
GType child_type_vfunc() const;
|
||||||
|
void set_drag_cursor (Gdk::Cursor);
|
||||||
|
|
||||||
|
protected:
|
||||||
bool horizontal;
|
bool horizontal;
|
||||||
|
|
||||||
void on_add (Gtk::Widget*);
|
void on_add (Gtk::Widget*);
|
||||||
|
|
@ -60,10 +62,15 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
|
||||||
bool handle_press_event (GdkEventButton*, Divider*);
|
bool handle_press_event (GdkEventButton*, Divider*);
|
||||||
bool handle_release_event (GdkEventButton*, Divider*);
|
bool handle_release_event (GdkEventButton*, Divider*);
|
||||||
bool handle_motion_event (GdkEventMotion*, 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);
|
void forall_vfunc (gboolean include_internals, GtkCallback callback, gpointer callback_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Gdk::Cursor drag_cursor;
|
||||||
|
bool did_move;
|
||||||
|
|
||||||
void reallocate (Gtk::Allocation const &);
|
void reallocate (Gtk::Allocation const &);
|
||||||
|
|
||||||
typedef std::list<Gtk::Widget*> Children;
|
typedef std::list<Gtk::Widget*> Children;
|
||||||
|
|
@ -76,11 +83,9 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
|
||||||
bool dragging;
|
bool dragging;
|
||||||
|
|
||||||
bool on_expose_event (GdkEventExpose* ev);
|
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;
|
Dividers dividers;
|
||||||
int divider_width;
|
int divider_width;
|
||||||
void add_divider ();
|
void add_divider ();
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <gdkmm/cursor.h>
|
||||||
#include "gtkmm2ext/pane.h"
|
#include "gtkmm2ext/pane.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
@ -28,10 +29,25 @@ using namespace std;
|
||||||
|
|
||||||
Pane::Pane (bool h)
|
Pane::Pane (bool h)
|
||||||
: horizontal (h)
|
: horizontal (h)
|
||||||
|
, did_move (false)
|
||||||
, divider_width (5)
|
, divider_width (5)
|
||||||
{
|
{
|
||||||
|
using namespace Gdk;
|
||||||
|
|
||||||
set_name ("Pane");
|
set_name ("Pane");
|
||||||
set_has_window (false);
|
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
|
void
|
||||||
|
|
@ -41,11 +57,11 @@ Pane::on_size_request (GtkRequisition* req)
|
||||||
|
|
||||||
/* iterate over all children, get their size requests */
|
/* iterate over all children, get their size requests */
|
||||||
|
|
||||||
/* horizontal pane is as high as its tallest child, but has no width
|
/* horizontal pane is as high as its tallest child, including the dividers.
|
||||||
* requirement.
|
* Its width is the sum of the children plus the dividers.
|
||||||
*
|
*
|
||||||
* vertical pane is as wide as its widest child, but has no height
|
* vertical pane is as wide as its widest child, including the dividers.
|
||||||
* requirement.
|
* Its height is the sum of the children plus the dividers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (horizontal) {
|
if (horizontal) {
|
||||||
|
|
@ -76,6 +92,7 @@ Pane::on_size_request (GtkRequisition* req)
|
||||||
GType
|
GType
|
||||||
Pane::child_type_vfunc() const
|
Pane::child_type_vfunc() const
|
||||||
{
|
{
|
||||||
|
/* We accept any number of any types of widgets */
|
||||||
return Gtk::Widget::get_type();
|
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_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_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_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->set_parent (*this);
|
||||||
d->show ();
|
d->show ();
|
||||||
d->fract = 0.5;
|
d->fract = 0.5;
|
||||||
|
|
@ -121,7 +140,6 @@ Pane::on_size_allocate (Gtk::Allocation& alloc)
|
||||||
void
|
void
|
||||||
Pane::reallocate (Gtk::Allocation const & alloc)
|
Pane::reallocate (Gtk::Allocation const & alloc)
|
||||||
{
|
{
|
||||||
Children::size_type n = 0;
|
|
||||||
int remaining;
|
int remaining;
|
||||||
int xpos = alloc.get_x();
|
int xpos = alloc.get_x();
|
||||||
int ypos = alloc.get_y();
|
int ypos = alloc.get_y();
|
||||||
|
|
@ -132,6 +150,7 @@ Pane::reallocate (Gtk::Allocation const & alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (children.size() == 1) {
|
if (children.size() == 1) {
|
||||||
|
/* only child gets the full allocation */
|
||||||
children.front()->size_allocate (alloc);
|
children.front()->size_allocate (alloc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +165,7 @@ Pane::reallocate (Gtk::Allocation const & alloc)
|
||||||
Children::iterator next;
|
Children::iterator next;
|
||||||
Dividers::iterator div;
|
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;
|
Gtk::Allocation child_alloc;
|
||||||
next = child;
|
next = child;
|
||||||
|
|
@ -155,12 +174,12 @@ Pane::reallocate (Gtk::Allocation const & alloc)
|
||||||
child_alloc.set_x (xpos);
|
child_alloc.set_x (xpos);
|
||||||
child_alloc.set_y (ypos);
|
child_alloc.set_y (ypos);
|
||||||
|
|
||||||
if (n >= dividers.size()) {
|
if (next == children.end()) {
|
||||||
/* the next child gets all the remaining space */
|
/* last child gets all the remaining space */
|
||||||
fract = 1.0;
|
fract = 1.0;
|
||||||
} else {
|
} else {
|
||||||
/* the next child gets the fraction of the remaining space given by the divider that follows it */
|
/* child gets the fraction of the remaining space given by the divider that follows it */
|
||||||
fract = dividers[n]->fract;
|
fract = (*div)->fract;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk::Requisition cr;
|
Gtk::Requisition cr;
|
||||||
|
|
@ -213,14 +232,15 @@ Pane::reallocate (Gtk::Allocation const & alloc)
|
||||||
bool
|
bool
|
||||||
Pane::on_expose_event (GdkEventExpose* ev)
|
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);
|
propagate_expose (**child, ev);
|
||||||
|
|
||||||
if (n < dividers.size()) {
|
if (div != dividers.end()) {
|
||||||
propagate_expose (*dividers[n], ev);
|
propagate_expose (**div, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +260,11 @@ bool
|
||||||
Pane::handle_release_event (GdkEventButton* ev, Divider* d)
|
Pane::handle_release_event (GdkEventButton* ev, Divider* d)
|
||||||
{
|
{
|
||||||
d->dragging = false;
|
d->dragging = false;
|
||||||
|
|
||||||
|
if (did_move) {
|
||||||
children.front()->queue_resize ();
|
children.front()->queue_resize ();
|
||||||
|
did_move = false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -248,6 +272,8 @@ Pane::handle_release_event (GdkEventButton* ev, Divider* d)
|
||||||
bool
|
bool
|
||||||
Pane::handle_motion_event (GdkEventMotion* ev, Divider* d)
|
Pane::handle_motion_event (GdkEventMotion* ev, Divider* d)
|
||||||
{
|
{
|
||||||
|
did_move = true;
|
||||||
|
|
||||||
if (!d->dragging) {
|
if (!d->dragging) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -305,12 +331,20 @@ Pane::set_divider (Dividers::size_type div, float fract)
|
||||||
{
|
{
|
||||||
bool redraw = false;
|
bool redraw = false;
|
||||||
|
|
||||||
while (dividers.size() <= div) {
|
Dividers::iterator d = dividers.begin();
|
||||||
add_divider ();
|
|
||||||
|
while (div--) {
|
||||||
|
++d;
|
||||||
|
if (d == dividers.end()) {
|
||||||
|
/* caller is trying to set divider that does not exist
|
||||||
|
* yet.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fract != dividers[div]->fract) {
|
if (fract != (*d)->fract) {
|
||||||
dividers[div]->fract = fract;
|
(*d)->fract = fract;
|
||||||
redraw = true;
|
redraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,23 +358,41 @@ Pane::set_divider (Dividers::size_type div, float fract)
|
||||||
float
|
float
|
||||||
Pane::get_divider (Dividers::size_type div)
|
Pane::get_divider (Dividers::size_type div)
|
||||||
{
|
{
|
||||||
if (div >= dividers.size()) {
|
Dividers::iterator d = dividers.begin();
|
||||||
return -1;
|
|
||||||
|
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
|
void
|
||||||
Pane::forall_vfunc (gboolean include_internals, GtkCallback callback, gpointer callback_data)
|
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);
|
callback ((*w)->gobj(), callback_data);
|
||||||
|
w = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (include_internals) {
|
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);
|
callback (GTK_WIDGET((*d)->gobj()), callback_data);
|
||||||
|
d = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -372,15 +424,17 @@ Pane::Divider::on_expose_event (GdkEventExpose* ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue