mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 16:24:57 +01:00
Enforce minimum pane sizes
* enforce minimum size of child widgets * honor manually set child-minsize in size-requests * ignore hidden children (eg. VCA) * clamp divider position (instead of just ignoring out-of-bounds moves)
This commit is contained in:
parent
2ed145cfd4
commit
c33f94f686
2 changed files with 69 additions and 30 deletions
|
|
@ -55,7 +55,7 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
|
|||
Child (Pane* p, Gtk::Widget* widget, uint32_t ms) : pane (p), w (widget), minsize (ms) {}
|
||||
};
|
||||
|
||||
typedef std::list<Child> Children;
|
||||
typedef std::vector<Child> Children;
|
||||
|
||||
Pane (bool horizontal);
|
||||
~Pane();
|
||||
|
|
@ -110,7 +110,7 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
|
|||
|
||||
void add_divider ();
|
||||
void handle_child_visibility ();
|
||||
bool fract_is_ok (Dividers::size_type, float fract);
|
||||
float constrain_fract (Dividers::size_type, float fract);
|
||||
|
||||
static void* notify_child_destroyed (void*);
|
||||
void* child_destroyed (Gtk::Widget*);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <gdkmm/cursor.h>
|
||||
#include "gtkmm2ext/pane.h"
|
||||
|
||||
|
|
@ -97,14 +98,26 @@ Pane::on_size_request (GtkRequisition* req)
|
|||
for (Children::iterator child = children.begin(); child != children.end(); ++child) {
|
||||
GtkRequisition r;
|
||||
|
||||
if (!child->w->is_visible ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
child->w->size_request (r);
|
||||
|
||||
if (horizontal) {
|
||||
largest.height = max (largest.height, r.height);
|
||||
largest.width += r.width;
|
||||
if (child->minsize) {
|
||||
largest.width += child->minsize;
|
||||
} else {
|
||||
largest.width += r.width;
|
||||
}
|
||||
} else {
|
||||
largest.width = max (largest.width, r.width);
|
||||
largest.height += r.height;
|
||||
if (child->minsize) {
|
||||
largest.height += child->minsize;
|
||||
} else {
|
||||
largest.height += r.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +215,15 @@ Pane::on_size_allocate (Gtk::Allocation& alloc)
|
|||
{
|
||||
reallocate (alloc);
|
||||
Container::on_size_allocate (alloc);
|
||||
|
||||
/* minumum pane size constraints */
|
||||
Dividers::size_type div = 0;
|
||||
for (Dividers::const_iterator d = dividers.begin(); d != dividers.end(); ++d, ++div) {
|
||||
Pane::set_divider (div, (*d)->fract);
|
||||
}
|
||||
// TODO this needs tweaking for panes with > 2 children
|
||||
// if a child grows, re-check the ones before it.
|
||||
assert (dividers.size () < 3);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -382,60 +404,83 @@ Pane::set_check_divider_position (bool yn)
|
|||
check_fract = yn;
|
||||
}
|
||||
|
||||
bool
|
||||
Pane::fract_is_ok (Dividers::size_type div, float fract)
|
||||
float
|
||||
Pane::constrain_fract (Dividers::size_type div, float fract)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
if (!check_fract) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (get_allocation().get_width() == 1 && get_allocation().get_height() == 1) {
|
||||
/* space not * allocated - * divider being set from startup code. Let it pass,
|
||||
since our goal is mostly to catch drags to a position that will interfere with window
|
||||
resizing.
|
||||
*/
|
||||
return true;
|
||||
* since our goal is mostly to catch drags to a position that will interfere with window
|
||||
* resizing.
|
||||
*/
|
||||
return fract;
|
||||
}
|
||||
|
||||
const float size = horizontal ? get_allocation().get_width() : get_allocation().get_height();
|
||||
|
||||
// TODO: optimize: cache in Pane::on_size_request
|
||||
Gtk::Requisition prev_req(children.at (div).w->size_request ());
|
||||
Gtk::Requisition next_req(children.at (div + 1).w->size_request ());
|
||||
float prev = divider_width + (horizontal ? prev_req.width : prev_req.height);
|
||||
float next = divider_width + (horizontal ? next_req.width : next_req.height);
|
||||
|
||||
if (children.at (div).minsize) {
|
||||
prev = children.at (div).minsize;
|
||||
}
|
||||
if (children.at (div + 1).minsize) {
|
||||
next = children.at (div + 1).minsize;
|
||||
}
|
||||
|
||||
if (size * fract < prev) {
|
||||
return prev / size;
|
||||
}
|
||||
if (size * (1.f - fract) < next) {
|
||||
return 1.f - next / size;
|
||||
}
|
||||
|
||||
if (!check_fract) {
|
||||
return fract;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* On Quartz, if the pane handle (divider) gets to
|
||||
be adjacent to the window edge, you can no longer grab it:
|
||||
any attempt to do so is interpreted by the Quartz window
|
||||
manager ("Finder") as a resize drag on the window edge.
|
||||
*/
|
||||
|
||||
|
||||
if (horizontal) {
|
||||
if (div == dividers.size() - 1) {
|
||||
if (get_allocation().get_width() * (1.0 - fract) < (divider_width*2)) {
|
||||
/* too close to right edge */
|
||||
return false;
|
||||
return 1.f - (divider_width * 2.f) / (float) get_allocation().get_width();
|
||||
}
|
||||
}
|
||||
|
||||
if (div == 0) {
|
||||
if (get_allocation().get_width() * fract < (divider_width*2)) {
|
||||
/* too close to left edge */
|
||||
return false;
|
||||
return (divider_width * 2.f) / (float)get_allocation().get_width();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (div == dividers.size() - 1) {
|
||||
if (get_allocation().get_height() * (1.0 - fract) < (divider_width*2)) {
|
||||
/* too close to bottom */
|
||||
return false;
|
||||
return 1.f - (divider_width * 2.f) / (float) get_allocation().get_height();
|
||||
}
|
||||
}
|
||||
|
||||
if (div == 0) {
|
||||
if (get_allocation().get_width() * fract < (divider_width*2)) {
|
||||
if (get_allocation().get_height() * fract < (divider_width*2)) {
|
||||
/* too close to top */
|
||||
return false;
|
||||
return (divider_width * 2.f) / (float) get_allocation().get_height();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
return fract;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -486,10 +531,7 @@ Pane::handle_motion_event (GdkEventMotion* ev, Divider* d)
|
|||
}
|
||||
|
||||
new_fract = min (1.0f, max (0.0f, new_fract));
|
||||
|
||||
if (!fract_is_ok (div, new_fract)) {
|
||||
return true;
|
||||
}
|
||||
new_fract = constrain_fract (div, new_fract);
|
||||
|
||||
if (new_fract != d->fract) {
|
||||
d->fract = new_fract;
|
||||
|
|
@ -517,10 +559,7 @@ Pane::set_divider (Dividers::size_type div, float fract)
|
|||
}
|
||||
|
||||
fract = max (0.0f, min (1.0f, fract));
|
||||
|
||||
if (!fract_is_ok (div, fract)) {
|
||||
return;
|
||||
}
|
||||
fract = constrain_fract (div, fract);
|
||||
|
||||
if (fract != (*d)->fract) {
|
||||
(*d)->fract = fract;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue