64 using CairoC = PCairoContext
const&;
65 using StyleC = PStyleContext
const&;
69 const int INITIAL_TIMERULER_HEIGHT_px = 30;
70 const int INITIAL_CONTENT_HEIGHT_px = 100;
71 const int MINIMAL_CONTENT_WIDTH_px = 100;
78 slopeClassName(
int depth)
82 case 1:
return CLASS_slope_deep1;
83 case 2:
return CLASS_slope_deep2;
84 case 3:
return CLASS_slope_deep3;
85 case 4:
return CLASS_slope_deep4;
86 default:
return CLASS_slope_verydeep;
89 const uint SLOPE_CAP_DEPTH = 5;
100 static bool styleSetupDone{
false};
101 if (styleSetupDone)
return;
103 StyleC styleRuler{trackRulerStyle.getAdvice()};
107 + styleRuler->get_margin().get_bottom()
108 + styleRuler->get_border().get_top()
109 + styleRuler->get_border().get_bottom()
110 + styleRuler->get_padding().get_top()
111 + styleRuler->get_padding().get_bottom()
114 + styleBody->get_margin().get_bottom()
115 + styleBody->get_padding().get_top()
116 + styleBody->get_padding().get_bottom()
119 + styleBody->get_padding().get_top()
124 for (uint depth=SLOPE_CAP_DEPTH; depth>0; --depth)
127 styleBody->add_class (slopeClassName(depth));
132 styleBody->remove_class (slopeClassName(depth));
135 styleSetupDone =
true;
167 fillBackground (StyleC style,
int height)
169 style->render_background (cox_
179 : cox_{currentDrawContext}
181 , styleR_{trackRulerStyle.getAdvice()}
203 int topMargin = style_->get_margin().get_top();
212 int bottomPad = pad + style_->get_margin().get_bottom();
221 int marTop = styleR_->get_margin().get_top();
222 int marBot = styleR_->get_margin().get_bottom();
223 int padTop = styleR_->get_padding().get_top();
224 int padBot = styleR_->get_padding().get_bottom();
225 int frameT = styleR_->get_border().get_top();
226 int frameB = styleR_->get_border().get_bottom();
228 int heightWithFrame = contentHeight + padTop+padBot + frameT+frameB;
231 fillBackground(styleR_, heightWithFrame);
232 styleR_->render_frame (cox_
238 line_ += heightWithFrame;
254 int marTop = style_->get_margin().get_top();
255 int marBot = style_->get_margin().get_bottom();
256 int padTop = style_->get_padding().get_top();
257 int padBot = style_->get_padding().get_bottom();
258 int heightWithPadding = contentHeight + padTop+padBot;
261 fillBackground (style_, heightWithPadding);
262 line_ += heightWithPadding;
272 style_->add_class (slopeClassName (1));
273 int slopeWidth = style_->get_border().get_top();
274 style_->render_frame_gap(cox_
275 ,visible_.b - slopeWidth
277 ,visible_.delta() + 2*slopeWidth
280 ,Gtk::PositionType::POS_BOTTOM
282 ,visible_.e + 2*slopeWidth
285 style_->remove_class (slopeClassName(1));
299 style_->add_class (slopeClassName(n));
300 int slopeWidth = style_->get_border().get_bottom();
302 style_->render_frame_gap(cox_
303 ,visible_.b - slopeWidth
305 ,visible_.delta() + 2*slopeWidth
308 ,Gtk::PositionType::POS_TOP
310 ,visible_.e + 2*slopeWidth
313 style_->remove_class (slopeClassName(n));
314 line_ += 2*slopeWidth;
318 using AbstractTrackRenderer::AbstractTrackRenderer;
332 line_ += style_->get_margin().get_top();
341 line_ += pad + style_->get_margin().get_bottom();
349 int marTop = styleR_->get_margin().get_top();
350 int marBot = styleR_->get_margin().get_bottom();
351 int padTop = styleR_->get_padding().get_top();
352 int padBot = styleR_->get_padding().get_bottom();
353 int frameT = styleR_->get_border().get_top();
354 int frameB = styleR_->get_border().get_bottom();
356 int heightWithFrame = contentHeight + padTop+padBot + frameT+frameB;
378 int marTop = style_->get_margin().get_top();
379 int marBot = style_->get_margin().get_bottom();
380 int padTop = style_->get_padding().get_top();
381 int padBot = style_->get_padding().get_bottom();
382 int heightWithPadding = contentHeight + padTop+padBot;
395 style_->add_class (slopeClassName (1));
396 int slopeWidth = style_->get_border().get_top();
398 style_->remove_class (slopeClassName(1));
407 style_->add_class (slopeClassName(n));
408 int slopeWidth = style_->get_border().get_bottom();
410 style_->remove_class (slopeClassName(n));
415 using AbstractTrackRenderer::AbstractTrackRenderer;
419 template<
class PINT,
bool isRuler>
423 return [&](CairoC cox)
425 PINT concreteRenderScheme{cox, layout};
426 getProfile().performWith (concreteRenderScheme, isRuler);
433 const bool RULER =
true;
434 const bool BODY =
false;
441 BodyCanvasWidget::~BodyCanvasWidget() { }
444 BodyCanvasWidget::BodyCanvasWidget (
DisplayManager& displayManager)
445 : Glib::ObjectBase(
"body")
446 , Gtk::Box{Gtk::ORIENTATION_VERTICAL}
447 , layout_{displayManager}
451 , rulerArea_{contentArea_.get_hadjustment(), Gtk::Adjustment::create (0,0,0,0,0,0)}
452 , rulerCanvas_{makeRenderer<Grounding,RULER>(layout_,getProfile), makeRenderer<Overlay,RULER>(layout_,getProfile)}
453 , mainCanvas_ {makeRenderer<Grounding,BODY> (layout_,getProfile), makeRenderer<Overlay,BODY> (layout_,getProfile)}
455 get_style_context()->add_class(CLASS_timeline);
456 get_style_context()->add_class(CLASS_timeline_body);
464 maybeRebuildLayout();
469 adjustCanvasSize(MINIMAL_CONTENT_WIDTH_px, INITIAL_CONTENT_HEIGHT_px, INITIAL_TIMERULER_HEIGHT_px);
471 this->set_border_width (0);
472 this->property_expand() =
true;
473 this->pack_start (rulerArea_, Gtk::PACK_SHRINK);
474 this->pack_start (contentArea_, Gtk::PACK_EXPAND_WIDGET);
476 rulerArea_.set_shadow_type (Gtk::SHADOW_NONE);
477 rulerArea_.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
478 rulerArea_.property_expand() =
false;
479 rulerArea_.add (rulerCanvas_);
480 contentArea_.set_shadow_type (Gtk::SHADOW_NONE);
481 contentArea_.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
482 contentArea_.property_expand() =
true;
483 contentArea_.add (mainCanvas_);
502 rootBody_ = &rootTrackBody;
506 BodyCanvasWidget::disable()
529 while (rootBody_ and isnil (profile_))
532 layout_.triggerDisplayEvaluation();
534 ENSURE (not isnil (profile_),
"DisplayEvaluation logic broken");
549 auto adjust = [](Gtk::Layout& canvas, guint newWidth, guint newHeight) ->
void 551 guint currWidth{0}, currHeight{0};
552 canvas.get_size(currWidth, currHeight);
553 if (currWidth != newWidth or currHeight != newHeight)
555 canvas.set_size(newWidth, newHeight);
559 canvas.set_size_request(MINIMAL_CONTENT_WIDTH_px, newHeight);
563 adjust (rulerCanvas_, canvasWidth, rulerHeight);
564 adjust (mainCanvas_, canvasWidth, contentHeight);
569 BodyCanvasWidget::forceRedraw()
571 rulerCanvas_.queue_draw();
572 mainCanvas_.queue_draw();
576 BodyCanvasWidget::getCanvas (
int yPos)
585 BodyCanvasWidget::hook (Gtk::Widget& widget,
int xPos,
int yPos)
588 getCanvas(yPos).put (widget, xPos, yPos);
592 BodyCanvasWidget::remove (Gtk::Widget& widget)
595 getCanvas(0).remove (widget);
599 BodyCanvasWidget::move (Gtk::Widget& widget,
int xPos,
int yPos)
602 getCanvas(yPos).move (widget, xPos, yPos);
620 uint contentHeight = rootBody_->establishTrackSpace (profile_);
621 uint rulerHeight = rootBody_->calcRulerHeight();
622 adjustCanvasSize(layout_.getPixSpan().delta(), contentHeight, rulerHeight);
636 TimelineCanvas::TimelineCanvas (_Renderer groundingFun, _Renderer overlayFun)
638 , renderGrounding_{groundingFun}
639 , renderOverlay_{overlayFun}
661 bool event_is_handled = Gtk::Layout::on_draw(cox);
668 return event_is_handled;
682 auto adjH = get_hadjustment();
683 auto adjV = get_vadjustment();
684 double offH = adjH->get_value();
685 double offV = adjV->get_value();
688 cox->translate(-offH, -offV);
710 renderGrounding_(cox);
void close(uint n) override
paint closing slope to finish nested sub tracks
void maybeRebuildLayout()
Possibly (re)build the allocation and distribution of layout space.
PixSpan getPixSpan()
the overall horizontal pixel span to cover by this timeline
SignalStructureChange signalStructureChange_
signal to be invoked whenever the virtual structure of the corresponding timeline changes...
void closeCanvas(CairoC)
Finish and close the virtual drawing canvas established by openCanvas().
Access point for the advised entity (client).
std::function< TrackProfile &()> ProfileGetter
a way to get and possibly (re)compute the current TrackProfile
Mix-in interface to allow for concrete CanvasHooked widgets to adapt themselves to the metric current...
Widget to render the body of timeline display, by custom drawing into a canvas control.
void coda(uint pad) override
finish painting the track body area
void content(uint contentHeight) override
fill background of track content area with the given vertical extension
static Decoration decoration
storage for common style/padding settings
void ruler(uint contentHeight) override
draw grounding of an overview/ruler track with the given height
void open() override
render overlays covering the opening slope towards nested tracks
void coda(uint pad) override
finish painting overlays a the bottom of the track body area
void openCanvas(CairoC)
Prepare the drawing canvas to work within our virtual canvas coordinate system.
Lumiera's internal time value datatype.
void prelude() override
overlays to show at top of the track body area
void drawOverlays(CairoC)
model::DisplayMetric & getMetric() const override
access the component to handle layout metric
void gap(uint h) override
render overlays on top of padding/gap
void ruler(uint contentHeight) override
draw overlays on top of overview/ruler track
Visitor and state holder for a collaborative layout adjustment pass.
Expecting Advice and giving Advice: a cross-cutting collaboration of loosely coupled participants...
Borders borders
width of up to 6 levels of combined upward slope borders (defined in CSS)
Abstraction: service for the widgets to translate themselves into screen layout.
void content(uint contentHeight) override
place overlays on top of of track content area,
void prelude() override
create spacing at the top of the track body area
Description of the structure and arrangement of tracks for display in the UI.
void adjustCanvasSize(int canvasWidth, int totalHeight, int rulerHeight)
After the (recent) display evaluation pass has negotiated the required space for the currently presen...
Lumiera GTK UI implementation root.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
void drawGrounding(CairoC)
Establish and render the structure of (possibly nested) tracks and overview rulers.
void gap(uint h) override
insert additional padding/gap (typically below a ruler)
void installForkRoot(TrackBody &rootTrackBody)
The Lumiera Timeline model does not rely on a list of tracks, as most conventional video editing soft...
Helper to organise and draw the space allocated for a fork of sub-tracks.
This helper class serves to manage the layout and display of the horizontally extended space of a "tr...
virtual bool on_draw(CairoC) override
Custom drawing of the timeline content area.
void close(uint n) override
render overlays covering the closing slope towards nested tracks
Abstraction to build the layout for the track spaces within timeline display.
void establishLayout(DisplayEvaluation &) override
respond to the DisplayEvaluation pass.
Definition of access keys for uniform UI styling.
void slotStructureChange() noexcept
force rebuilding of theTrackProfile whenever the global timeline structure changes ...
A set of basic GTK includes for the UI.
void setupAdditionalTrackPadding_fromCSS()
Adjust the vertical space to accommodate for additional decorations as required by the CSS style rule...
Interface for coordination of the overall timeline display.
void open() override
paint opening slope to enter nested sub tracks
lumiera::advice::Request< PStyleContext > trackBodyStyle
request a pre-defined CSS style context for the track body