Advanced code in the HeaderContainer
This commit is contained in:
parent
5e60921e14
commit
c2d43aba2b
7 changed files with 170 additions and 48 deletions
|
|
@ -152,14 +152,13 @@ style "timeline_ruler" = "default_base"
|
|||
gtkmm__CustomObject_TimelineRuler::playback_period_arrow_stem_size = 3
|
||||
}
|
||||
|
||||
style "timeline_header_base" = "default_base"
|
||||
style "header_container" = "default_base"
|
||||
{
|
||||
|
||||
gtkmm__CustomObject_HeaderContainer::heading_margin = 4
|
||||
}
|
||||
|
||||
class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body"
|
||||
class "gtkmm__CustomObject_TimelineRuler" style:highest "timeline_ruler"
|
||||
|
||||
widget "*TimelineHeaderBaseUnselected" style:highest "timeline_header_base"
|
||||
class "gtkmm__CustomObject_HeaderContainer" style:highest "header_container"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,17 +68,17 @@ TimelineWidget::TimelineWidget() :
|
|||
|
||||
set_time_scale(GAVL_TIME_SCALE / 200);
|
||||
set_selection(2000000, 4000000);
|
||||
|
||||
|
||||
tracks.push_back(&video1);
|
||||
tracks.push_back(&video2);
|
||||
|
||||
update_tracks();
|
||||
|
||||
attach(*body, 1, 2, 1, 2, FILL|EXPAND, FILL|EXPAND);
|
||||
attach(*ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK);
|
||||
attach(*headerContainer, 0, 1, 1, 2, SHRINK, FILL|EXPAND);
|
||||
attach(horizontalScroll, 1, 2, 2, 3, FILL|EXPAND, SHRINK);
|
||||
attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND);
|
||||
|
||||
tracks.push_back(&video1);
|
||||
tracks.push_back(&video2);
|
||||
|
||||
update_tracks();
|
||||
|
||||
set_tool(timeline::Arrow);
|
||||
}
|
||||
|
|
@ -376,6 +376,7 @@ TimelineWidget::update_scroll()
|
|||
else if(y_scroll_length > 0 && !verticalScroll.is_visible())
|
||||
verticalScroll.show();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -390,6 +391,7 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event)
|
|||
REQUIRE(event != NULL);
|
||||
ruler->set_mouse_chevron_offset(event->x);
|
||||
mouseHoverSignal.emit(x_to_time(event->x));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ public:
|
|||
|
||||
/* ===== Events ===== */
|
||||
protected:
|
||||
|
||||
void on_scroll();
|
||||
|
||||
void on_size_allocate(Gtk::Allocation& allocation);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ namespace widgets {
|
|||
namespace timeline {
|
||||
|
||||
HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline_widget) :
|
||||
timelineWidget(timeline_widget)
|
||||
Glib::ObjectBase("HeaderContainer"),
|
||||
timelineWidget(timeline_widget),
|
||||
margin(-1)
|
||||
{
|
||||
REQUIRE(timeline_widget != NULL);
|
||||
|
||||
|
|
@ -48,25 +50,32 @@ HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline
|
|||
// so that we get notified when the view shifts
|
||||
timelineWidget->verticalAdjustment.signal_value_changed().connect(
|
||||
sigc::mem_fun(this, &HeaderContainer::on_scroll) );
|
||||
|
||||
// Install style properties
|
||||
register_styles();
|
||||
}
|
||||
|
||||
void
|
||||
HeaderContainer::update_headers()
|
||||
{
|
||||
ASSERT(timelineWidget != NULL);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
// Remove any pre-exisitng headers
|
||||
BOOST_FOREACH( RootHeader header, rootHeaders )
|
||||
{
|
||||
header.widget->unparent();
|
||||
}
|
||||
|
||||
rootHeaders.clear();
|
||||
|
||||
// Add fresh headers
|
||||
BOOST_FOREACH( Track* track, timelineWidget->tracks )
|
||||
{
|
||||
ASSERT(track != NULL);
|
||||
|
||||
Glib::RefPtr<Gtk::Frame> headerFrame(new Gtk::Frame());
|
||||
headerFrame->add(track->get_header_widget());
|
||||
headerFrame->set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
|
||||
headerFrame->set_name ("TimelineHeaderBaseUnselected");
|
||||
headerFrame->set_parent(*this);
|
||||
headerFrame->show();
|
||||
|
||||
const RootHeader header = { headerFrame, track };
|
||||
|
||||
const RootHeader header = { &track->get_header_widget(), track };
|
||||
header.widget->set_parent(*this);
|
||||
|
||||
rootHeaders.push_back(header);
|
||||
}
|
||||
|
||||
|
|
@ -78,11 +87,9 @@ HeaderContainer::on_realize()
|
|||
{
|
||||
set_flags(Gtk::NO_WINDOW);
|
||||
|
||||
ensure_style();
|
||||
|
||||
// Call base class:
|
||||
Gtk::Widget::on_realize();
|
||||
|
||||
Gtk::Container::on_realize();
|
||||
|
||||
// Create the GdkWindow:
|
||||
GdkWindowAttr attributes;
|
||||
memset(&attributes, 0, sizeof(attributes));
|
||||
|
|
@ -123,9 +130,18 @@ HeaderContainer::on_unrealize()
|
|||
|
||||
void
|
||||
HeaderContainer::on_size_request (Requisition* requisition)
|
||||
{
|
||||
{
|
||||
// Initialize the output parameter:
|
||||
*requisition = Gtk::Requisition();
|
||||
|
||||
// We don't care about the size of all the child widgets, but if we
|
||||
// don't send the size request down the tree, some widgets fail to
|
||||
// calculate their text layout correctly.
|
||||
BOOST_FOREACH( RootHeader header, rootHeaders )
|
||||
{
|
||||
if(header.widget != NULL && header.widget->is_visible())
|
||||
header.widget->size_request();
|
||||
}
|
||||
|
||||
requisition->width = TimelineWidget::HeaderWidth;
|
||||
requisition->height = 0;
|
||||
|
|
@ -148,13 +164,51 @@ HeaderContainer::on_size_allocate (Allocation& allocation)
|
|||
void
|
||||
HeaderContainer::forall_vfunc(gboolean /* include_internals */,
|
||||
GtkCallback callback, gpointer callback_data)
|
||||
{
|
||||
{
|
||||
BOOST_FOREACH( RootHeader &header, rootHeaders )
|
||||
{
|
||||
ASSERT(header.widget);
|
||||
callback(header.widget->gobj(), callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HeaderContainer::on_expose_event(GdkEventExpose *event)
|
||||
{
|
||||
if(gdkWindow)
|
||||
{
|
||||
int offset = 0;
|
||||
const int y_scroll_offset = timelineWidget->get_y_scroll_offset();
|
||||
|
||||
Glib::RefPtr<Style> style = get_style();
|
||||
const Allocation container_allocation = get_allocation();
|
||||
|
||||
read_styles();
|
||||
|
||||
// Paint a border underneath all the root headers
|
||||
BOOST_FOREACH( RootHeader &header, rootHeaders )
|
||||
{
|
||||
ASSERT(header.widget);
|
||||
ASSERT(header.track != NULL);
|
||||
|
||||
const int height = header.track->get_height();
|
||||
ASSERT(height >= 0);
|
||||
|
||||
style->paint_box(
|
||||
gdkWindow, STATE_NORMAL, SHADOW_OUT,
|
||||
Gdk::Rectangle(
|
||||
0, 0,
|
||||
container_allocation.get_width(),
|
||||
container_allocation.get_height()),
|
||||
*this, "", 0, offset - y_scroll_offset,
|
||||
container_allocation.get_width(), height);
|
||||
|
||||
offset += height + TimelineWidget::TrackPadding;
|
||||
}
|
||||
}
|
||||
|
||||
return Container::on_expose_event(event);
|
||||
}
|
||||
|
||||
void
|
||||
HeaderContainer::on_scroll()
|
||||
|
|
@ -167,12 +221,20 @@ HeaderContainer::on_scroll()
|
|||
void
|
||||
HeaderContainer::layout_headers()
|
||||
{
|
||||
ASSERT(timelineWidget != NULL);
|
||||
ASSERT(timelineWidget != NULL);
|
||||
|
||||
// We can't layout before the widget has been set up
|
||||
if(!gdkWindow)
|
||||
return;
|
||||
|
||||
int offset = 0;
|
||||
const int y_scroll_offset = timelineWidget->get_y_scroll_offset();
|
||||
|
||||
const Allocation container_allocation = get_allocation();
|
||||
read_styles();
|
||||
|
||||
const Allocation container_allocation = get_allocation();
|
||||
const int header_width = container_allocation.get_width ()
|
||||
- margin * 2;
|
||||
|
||||
BOOST_FOREACH( RootHeader &header, rootHeaders )
|
||||
{
|
||||
|
|
@ -183,14 +245,38 @@ HeaderContainer::layout_headers()
|
|||
ASSERT(height >= 0);
|
||||
|
||||
Gtk::Allocation header_allocation;
|
||||
header_allocation.set_x (0);
|
||||
header_allocation.set_y (offset - y_scroll_offset);
|
||||
header_allocation.set_width (container_allocation.get_width ());
|
||||
header_allocation.set_height (height);
|
||||
header.widget->size_allocate(header_allocation);
|
||||
header_allocation.set_x (margin);
|
||||
header_allocation.set_y (offset - y_scroll_offset + margin);
|
||||
header_allocation.set_width (header_width);
|
||||
header_allocation.set_height (height - margin * 2);
|
||||
|
||||
if(header.widget->is_visible())
|
||||
header.widget->size_allocate (header_allocation);
|
||||
|
||||
offset += height + TimelineWidget::TrackPadding;
|
||||
}
|
||||
|
||||
// Repaint the background of our parenting
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void
|
||||
HeaderContainer::register_styles() const
|
||||
{
|
||||
GtkWidgetClass *klass = GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj()));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_int("heading_margin",
|
||||
"Heading Margin",
|
||||
"The amount of padding around each header pixels.",
|
||||
0, G_MAXINT, 4, G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
void
|
||||
HeaderContainer::read_styles()
|
||||
{
|
||||
if(margin <= 0)
|
||||
get_style_property("heading_margin", margin);
|
||||
}
|
||||
|
||||
} // namespace timeline
|
||||
|
|
|
|||
|
|
@ -69,12 +69,12 @@ public:
|
|||
/* ===== Overrides ===== */
|
||||
private:
|
||||
/**
|
||||
* And event handler for the window realized signal.
|
||||
* An event handler for the window realized signal.
|
||||
*/
|
||||
void on_realize();
|
||||
|
||||
/**
|
||||
* And event handler for the window unrealized signal.
|
||||
* An event handler for the window unrealized signal.
|
||||
*/
|
||||
void on_unrealize();
|
||||
|
||||
|
|
@ -97,9 +97,15 @@ private:
|
|||
**/
|
||||
void forall_vfunc(gboolean include_internals, GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
|
||||
|
||||
/* ===== Events ===== */
|
||||
private:
|
||||
|
||||
/**
|
||||
* An event handler for when the window must be redrawn.
|
||||
*/
|
||||
bool on_expose_event(GdkEventExpose *event);
|
||||
|
||||
/**
|
||||
* This event is called when the scroll bar moves.
|
||||
*/
|
||||
|
|
@ -114,12 +120,32 @@ private:
|
|||
*/
|
||||
void layout_headers();
|
||||
|
||||
/**
|
||||
* Registers all the styles that this class will respond to.
|
||||
*/
|
||||
void register_styles() const;
|
||||
|
||||
/**
|
||||
* Reads styles from the present stylesheet.
|
||||
*/
|
||||
void read_styles();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The owner TimelineWidget of which this class is a helper
|
||||
*/
|
||||
lumiera::gui::widgets::TimelineWidget *timelineWidget;
|
||||
|
||||
/**
|
||||
* The widget's window object.
|
||||
*
|
||||
* @note This is needed for the sake of clipping when
|
||||
* widgets are scrolled.
|
||||
*/
|
||||
Glib::RefPtr<Gdk::Window> gdkWindow;
|
||||
|
||||
//----- Header List -----//
|
||||
|
||||
/**
|
||||
* A structure to represent a header widget and it's
|
||||
|
|
@ -127,7 +153,7 @@ private:
|
|||
*/
|
||||
struct RootHeader
|
||||
{
|
||||
Glib::RefPtr<Gtk::Widget> widget;
|
||||
Gtk::Widget *widget;
|
||||
Track *track;
|
||||
};
|
||||
|
||||
|
|
@ -137,13 +163,13 @@ private:
|
|||
*/
|
||||
std::vector< RootHeader > rootHeaders;
|
||||
|
||||
//----- Style Values -----//
|
||||
|
||||
/**
|
||||
* The widget's window object.
|
||||
*
|
||||
* @note This is needed for the sake of clipping when
|
||||
* widgets are scrolled.
|
||||
*/
|
||||
Glib::RefPtr<Gdk::Window> gdkWindow;
|
||||
* The style value which indicates the amount of padding around each
|
||||
* header pixels.
|
||||
**/
|
||||
int margin;
|
||||
};
|
||||
|
||||
} // namespace timeline
|
||||
|
|
|
|||
|
|
@ -22,15 +22,20 @@
|
|||
|
||||
#include "track.hpp"
|
||||
|
||||
using namespace Gtk;
|
||||
|
||||
namespace lumiera {
|
||||
namespace gui {
|
||||
namespace widgets {
|
||||
namespace timeline {
|
||||
|
||||
Track::Track() :
|
||||
label("XHeaderTest")
|
||||
label1("test1"), label2("test2"), label3("test3"), label4("test4")
|
||||
{
|
||||
headerWidget.pack_start(label);
|
||||
headerWidget.pack_start(label1, PACK_EXPAND_WIDGET);
|
||||
headerWidget.pack_start(label2, PACK_EXPAND_WIDGET);
|
||||
headerWidget.pack_start(label3, PACK_EXPAND_WIDGET);
|
||||
headerWidget.pack_start(label4, PACK_EXPAND_WIDGET);
|
||||
}
|
||||
|
||||
Gtk::Widget&
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
/** @file timeline/track.hpp
|
||||
/** @file widgets/timeline/track.hpp
|
||||
** This file contains the definition of timeline track object
|
||||
*/
|
||||
|
||||
|
|
@ -48,7 +48,10 @@ public:
|
|||
|
||||
protected:
|
||||
Gtk::VBox headerWidget;
|
||||
Gtk::Label label;
|
||||
Gtk::Label label1;
|
||||
Gtk::Label label2;
|
||||
Gtk::CheckButton label3;
|
||||
Gtk::Button label4;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue