From fc0fcad4d69347269f664504fd7e74e15b969c87 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 6 Mar 2023 01:51:35 +0100 Subject: [PATCH] Timeline: implement structure connections for sub-Tracks (closes: #1018) This completes the initial implementation round for the TrackHead. - arrangement and layout for nested sub-Tracks is now settled - a graphical representation of scope nesting was implemented Postponed for later... - still some minor discrepancies on synchronisation of vertical space between TrackHead and custom drawing in the body (off-by-one?) - Expanding / Collapsing of Tracks - Implement actual Controls to influence the Scope, e.g. Volume, Mix-Mode - Dynamically indicate selection and Muting on the structure display --- src/stage/lumiera-light-theme-complement.css | 1 + src/stage/timeline/stave-bracket-widget.cpp | 90 ++++- src/stage/timeline/stave-bracket-widget.hpp | 32 +- src/stage/timeline/track-head-widget.cpp | 36 +- src/stage/timeline/track-head-widget.hpp | 2 + wiki/draw/TrackHeadNesting.png | Bin 6740 -> 7207 bytes wiki/thinkPad.ichthyo.mm | 336 +++++++++++++++++-- 7 files changed, 453 insertions(+), 44 deletions(-) diff --git a/src/stage/lumiera-light-theme-complement.css b/src/stage/lumiera-light-theme-complement.css index 1eba6dc61..461bb2d19 100644 --- a/src/stage/lumiera-light-theme-complement.css +++ b/src/stage/lumiera-light-theme-complement.css @@ -88,4 +88,5 @@ */ .fork__bracket { padding-left: 2px; + padding-right: 1px; } diff --git a/src/stage/timeline/stave-bracket-widget.cpp b/src/stage/timeline/stave-bracket-widget.cpp index d7e9cf617..7ebbde256 100644 --- a/src/stage/timeline/stave-bracket-widget.cpp +++ b/src/stage/timeline/stave-bracket-widget.cpp @@ -41,10 +41,9 @@ ** defined standard font in device units, and uses this _em_ size as reference to derive a _scale_ factor, ** which is then applied to the drawing as a whole — taking into account any given vertical size limitations ** as imposed by the general nested trade head structure. - ** - the FreeCAD document can be found at `doc/devel/draw/StaveBracket.FCStd` - ** - see also the SVG image `doc/devel/draw/StaveBracket.svg` for explanation of geometry - ** - ** @todo WIP as of 3/2023 + ** @see the FreeCAD document can be found at `doc/devel/draw/StaveBracket.FCStd` + ** @see SVG image `doc/devel/draw/StaveBracket.svg` for explanation of geometry + ** @see explanation on page #TrackStaveBracket in the TiddlyWiki ** */ @@ -73,7 +72,7 @@ namespace timeline { const double BASE_WIDTH_PER_EM = 0.5; // scale factor: width of double line relative to font size const double ORG = 0.0; - const double PHI = (1.0 + sqrt(5)) / 2.0; // Golden Ratio Φ ≔ ½(1+√5) ≈ 1.6180339887498948482 + const double PHI = (1.0 + sqrt(5)) / 2.0; // Golden Ratio Φ ≔ ½·(1+√5) ≈ 1.6180339887498948482 const double PHI_MAJOR = PHI - 1.0; // 1/Φ = Φ-1 const double PHI_MINOR = 2.0 - PHI; // 1-1/Φ = 2-Φ const double PHISQUARE = 1.0 + PHI; // Φ² = Φ+1 @@ -150,7 +149,9 @@ namespace timeline { double determineScale (StyleC style, int givenHeight) { - auto maxScale = givenHeight / (2*PHISQUARE); + auto required = 2*PHISQUARE + style->get_padding().get_top() + + style->get_padding().get_bottom(); + auto maxScale = givenHeight / (required); return min (maxScale, baseWidth (style)); } @@ -162,14 +163,20 @@ namespace timeline { int calcRequiredWidth (StyleC style, int givenHeight) { - return ceil (PHISQUARE * determineScale (style,givenHeight)); + return ceil (PHISQUARE * determineScale (style,givenHeight) + +style->get_padding().get_right() + +style->get_padding().get_left() + ); } /** @return width for the drawing, without considering height limitation */ int calcDesiredWidth (StyleC style) { - return ceil (PHISQUARE * baseWidth (style)); + return ceil (PHISQUARE * baseWidth (style) + +style->get_padding().get_right() + +style->get_padding().get_left() + ); } /** place left anchor reference line to right side of bold bar. @@ -260,6 +267,70 @@ namespace timeline { cox->restore(); } + /** + * Indicate connection to nested sub-Track scopes. + * Draw a connector dot at each joint, and a arrow + * pointing towards the nested StaveBracket top. + * @todo simplistic implementation as of 3/23; + * could be made expandable /collapsable + */ + void + connect (CairoC cox, Gdk::RGBA colour + ,double leftX, double upperY, double lowerY, double width, double scale + ,std::vector connectors) + { + double limit = lowerY - upperY; + double line = leftX + scale*(LIN_LEFT + LIN_WIDTH/2); + double rad = scale * PHI_MAJOR; + cox->save(); + // shift connectors to join below top cap + cox->translate (line, upperY); + // fill circle with a lightened yellow hue + cox->set_source_rgb(1 - 0.2*(colour.get_red()) + ,1 - 0.2*(colour.get_green()) + ,1 - 0.5*(1 - colour.get_blue()) ); + // draw a circle joint on top of the small vertical line + for (uint off : connectors) + if (off <= limit) + { + cox->move_to(rad,off); + cox->arc ( 0,off, rad, 0, 2 * M_PI); + cox->close_path(); + } + // + cox->fill_preserve(); + cox->set_source_rgba(colour.get_red() + ,colour.get_green() + ,colour.get_blue() + ,colour.get_alpha()); + cox->set_line_width(scale*LIN_WIDTH*PHI_MAJOR); + cox->stroke(); + // + // draw connecting arrows... + cox->translate(rad,0); + // Note: arrow tip uses complete width, reaches into the padding-right + double len = width-line-rad-1; // -1 to create room for a sharp miter + ASSERT (len > 0); + double arr = len * PHI_MINOR; + double bas = scale * PHI_MINOR; + for (uint off : connectors) + if (off <= limit) + { + cox->move_to(ORG,off); + cox->line_to(arr,off); + // draw arrow head... + cox->move_to(arr,off-bas); + cox->line_to(len,off); + cox->line_to(arr,off+bas); + cox->close_path(); + } + cox->set_miter_limit(20); // to create sharp arrow tip + cox->fill_preserve(); + cox->stroke(); + // + cox->restore(); + } + }//(End)Implementation details (drawing design) @@ -271,6 +342,7 @@ namespace timeline { StaveBracketWidget::StaveBracketWidget () : _Base{} + , connectors_{} { get_style_context()->add_class (CLASS_fork_bracket); this->property_expand() = false; @@ -296,6 +368,7 @@ namespace timeline { StyleC style = this->get_style_context(); auto colour = style->get_color (Gtk::STATE_FLAG_NORMAL); int height = this->get_allocated_height(); + int width = this->get_width(); double scale = determineScale (style, height); double left = anchorLeft (style, scale); double upper = anchorUpper (style,scale); @@ -304,6 +377,7 @@ namespace timeline { drawCap (cox, colour, left, upper, scale, true); drawCap (cox, colour, left, lower, scale, false); drawBar (cox, colour, left, upper, lower, scale); + connect (cox, colour, left, upper, lower, width, scale, connectors_); return event_is_handled; } diff --git a/src/stage/timeline/stave-bracket-widget.hpp b/src/stage/timeline/stave-bracket-widget.hpp index 3ffd85f73..4586abd1a 100644 --- a/src/stage/timeline/stave-bracket-widget.hpp +++ b/src/stage/timeline/stave-bracket-widget.hpp @@ -30,13 +30,15 @@ ** the actual space allocation and positioning of sub-tracks in the layout; technicalities ** of actual drawing this structure is abstracted into this custom widget — allowing the ** track head to indicate the necessary layout constraints generic and recursively. + ** The relation to nested stave brackets for sub-Tracks can be indicated with a + ** connection joint and arrow; prerequisite is to provide the vertical offset. ** ** \par styling ** - styling is controlled via CSS, using the marker class \ref CLASS_fork_bracket ** - the »base width« of the vertical double line is based on the font's `em` setting ** - padding and colour attributes from CSS are observed ** - ** @todo WIP as of 3/2023 + ** @see TrackHeadWidget::structure_ ** */ @@ -46,6 +48,8 @@ #include "stage/gtk-base.hpp" +#include + namespace stage { namespace timeline { @@ -64,11 +68,14 @@ namespace timeline { : public Gtk::DrawingArea { using _Base = Gtk::DrawingArea; + std::vector connectors_; public: ~StaveBracketWidget(); + StaveBracketWidget(); - StaveBracketWidget (); + void clearConnectors(); + void addConnector (uint offset); private:/* ===== Internals ===== */ @@ -80,5 +87,26 @@ namespace timeline { }; + + inline void + StaveBracketWidget::clearConnectors() + { + connectors_.clear(); + } + + /** + * Request to draw a connector to the nested sub-Track's stave bracket. + * @param offset vertical location where the sub-Track starts, relative + * to the start of this stave bracket's start + * @remark called from the 2nd DisplayEvaluation pass, when linking the layout + * @see TrackHeadWidget::linkSubTrackPositions + */ + inline void + StaveBracketWidget::addConnector (uint offset) + { + connectors_.emplace_back (offset); + } + + }}// namespace stage::timeline #endif /*STAGE_TIMELINE_STAVE_BRACKET_WIDGET_H*/ diff --git a/src/stage/timeline/track-head-widget.cpp b/src/stage/timeline/track-head-widget.cpp index 88388df4e..0cb941364 100644 --- a/src/stage/timeline/track-head-widget.cpp +++ b/src/stage/timeline/track-head-widget.cpp @@ -81,13 +81,15 @@ namespace timeline { this->attach (headCtrl_, 1,1, 1,1); // corresponds to direct content this->attach (padding_, 1,2, 1,1);// used to sync with sub-track display this->property_expand() = false; // do not expand to fill + this->set_column_spacing(0); + this->set_row_spacing(0); this->show_all(); } HeadControlArea::HeadControlArea() : Gtk::Grid{} - , ctrlTODO_{"💡"} + , ctrlTODO_{"\n 💡"} { get_style_context()->add_class (CLASS_fork_control); ctrlTODO_.set_xalign (0.3); @@ -144,9 +146,14 @@ namespace timeline { void TrackHeadWidget::accommodateOverallHeight(uint overallHeight) { + uint discrepancy{0}; uint localHeight = getOverallHeight(); if (overallHeight > localHeight) - enforceExpansionHeight (overallHeight - getLabelHeight()); + { + enforceExpansionHeight (overallHeight - getLabelHeight()); + discrepancy = overallHeight-localHeight; + } + linkSubTrackPositions (discrepancy); } /** @@ -163,8 +170,29 @@ namespace timeline { if (directHeight > localHeight) enforceSyncPadHeight (directHeight - localHeight); } - - + + /** + * Coordinate the exact positions of sub-Track start during DisplayEvaluaton. + * @note assuming that layout for all sub-Tracks is already final when called + * @param discrepancy additional vertical offset incurred to reach a nominal height; + * this value is interspersed between the content cells and above the Children + */ + void + TrackHeadWidget::linkSubTrackPositions(uint discrepancy) + { + structure_.clearConnectors(); + uint offset = getContentHeight() + + getSyncPadHeight() + + discrepancy + + getLabelHeight() // offset by the label in the children + ; + for (uint child=0; child < childCnt_; ++child) + { + structure_.addConnector (offset); + offset += getHeightAt (1, child+3); + } + } + /** * @remark The Lumiera Timeline model does not rely on a list of tracks, as most conventional diff --git a/src/stage/timeline/track-head-widget.hpp b/src/stage/timeline/track-head-widget.hpp index 5ccd5e291..d0b942d0b 100644 --- a/src/stage/timeline/track-head-widget.hpp +++ b/src/stage/timeline/track-head-widget.hpp @@ -116,6 +116,8 @@ namespace timeline { /** Discard all nested sub track display widgets. */ void clearFork(); + void linkSubTrackPositions (uint); + /** get the height allocated at cell(x,y) */ uint getHeightAt (int left, int top) const; void enforceHeightAt(int left, int top, uint height); diff --git a/wiki/draw/TrackHeadNesting.png b/wiki/draw/TrackHeadNesting.png index 024a8f9b8cacbae03ea7f2aec56d41cbf952f88e..8412d50329b9a2cae4a6ed86ff46d54ccdafa039 100644 GIT binary patch literal 7207 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 literal 6740 zcmcInWmFqLmjxRx~8mu^Nky6}g zfwKK%&+d=!-=6(3_szUH@6LHM@4PcNRznT=6rTnk3k&P1lHxn?Ukk;;!qLWi@OO5+ zFJ+5`g@5R;4e|@Je?6 z+5e@2lE|MjH9bO|Uj&!4j-IJD!&|l&LKCiTd+vVQ6`1ag*IdbkBr1mRp40pCGSnaK zuV2}+wD8v4AloVH&VFMm_iVLx0tznjt`Vof8N~G_l=mUm?s6xXYR5ErH8nA*{4HzQ zOP|Szy}fz?;`m=C9>i1fYw=%`c!zGhU?=qvouXo0xeT2F_urRAcE)_yr`7`(gI~`E z(<@#q-`%2Mfv6vMuU&7(WIl@q114{Rjt;N#7Iqcve9;}xFGK-%2GOypC8uYQ?lc31HIu^eNk`4!HXBk{nK(s?Q@m+*OV5n-3=ojb5ANjpDft1CpAePopaIj}IGZtm zk44Mo!?*f%fnQScf({m4N+u@({5mA@tn|MUYmR*)?#H-R_GA<}E;I7GA9=^J5C}@R z{~6)NNjU^KU$`CDEC6m#NP}rBqU;X0C$WJ!HLNzOA?94tZjr16J-Hl$Qv!RATDJMZLpV~ODqEK@a~V}A>z${n`;A^#P60V& zL@I8h$TB*~yD!v~m8*ecRZYencT02(n#xD$yFb4f3e(p#Q`x~%>e7XSs~>+m#BO?m zC2iiRfSAAie2z8!jXz!z&P*?ss4ryO!bznsDQwQ3NX5j>uGF#1;vFJ?nD~vt{=TSr zBqZMGc=}G7nG$dH$nA#7etGwBq|b+8wG2+%X?~c{%p}}nSNMT99(&r z*tu~a{578wY1k7v99&<`?9FVT6R9C+xyVi*xC~Qo7ELbARdp@9)UO`M#LH1Ntb z@aPcB&Ku#~BL5(r-G+V4>blxSrf12~PDl`m+|Pah6o0oB`eMUX1Z5Bdo;js~lw7z! zq@L*}Kk1ZXCmQ|&XS1;lUF1n&d$}i4rA)Q=WnX2(0bP)uaQ+w;tK+zu#>j-#kQi}8 z;QU(3v`oQqQPeQiZms@;#c~!zrpuyQtln!K-{+hjsS9-81My$|Mnzd~6w+IAH{zgr zh~{s=o6(0YZ^GssUans3tjzo2FWUY3p1%Gn?Tv-TxuXDn^ge6#1WI8|Q@v{XxCw}1 z5)156ft-|=2vkLIX6u*|&pj{SRQfiu^6Aq5o28Up(7WF_5var!7ixEluSuQzh?%@S zY=B74T5XxGz*)@Kt5+P7ZExbFPzt64Ot~ROLk}Hn6`mRn4hn^|UItdmXg9sO*D76U zCB`jwC1w=OH43Ihk>i=>qND;Yt{sJpbf4B8gqtJ?=C&rRt$w46#2eD^H-Bd1s1u+@ z0&;d8gWSaQTp>o;=>8lUso-}_4k(zaZNJ#7U)dw9PL$3+y79e6nC-c!$6`z8lg0|s zz;!<=g5y;#e&lC3De@?{#x>T}8z@ydTbX)@Q~6wCeBZEbTRZ{^Zhk;3%A#AOPk-yyhW zcRI#I5fDI6h$zDy?H|+wyg`r9e125(+LvjLosHI3Iu>|PI>`URKZ38EnEdG&A;9V! z8%P@oxduiGdM&21E7i5#80bLV zbSH|04ci%hdOGNLjeoxGrq+~@)i*>@E zs3fnFVoyc!H)z&+Gm?+ap+ODt|1F;vdu{qkT zUq9=JkZibfrV}ZH@Kzp`Z&lct>J5 zB($zlQf7E3C6*B1J}MZEGU1w)7&@2N#G>wJ&2f4QVi;iLm3mIC5gJnr(4S|L?5O(@ z7koI|*z`x0If}2K(!PWDHj*+FDldB=$vOeFUA;|vR!rJ4ka`s(>PV>|txho2epMOP z_yg}DyVB@(zPnWpZ^c~-UDwWI+nZD}d{Wrc-Rnc&Qyq?W{d+XW@ok#Inlx!0!-ejfQ=E|mG|MqZ;-*2H7?Cdk}D}r2X^idb$-@Z3p1R2 z7AZ(4HdMg+aeA86=hb5-CC(&D&70m)_pOiXmpDP_W1pDeC&Rf$xH2*7q!VvW@BQPh zNHyW{dD2XfmC^@y=a&{S*@~1yr;Y7IRqxlXKSI$b_ij~P?7g^NE09#8P-f2)tEul~ zrR1+pp4~-1S(Jnv>GLpaWHOKaI6NxqhnO=D-wj3fSe_JO?cQncn8WimkKdWGygjd8l_loJ^Zp1Sc<<{fE>) zVXg8FacG_~P66(g$b4d6jtce zERX^OF#u0Fq2mR0nO9nolK_wrP3MQ_IL4&k=BbA-v~%USD*8fjiYK}6OH#^uyRc6~ zAJXAzK6!$Lg&kohC#Rt#C->h!Uo5Ow$wA4IihVM)1EyN>%;dO$529A@bGbj5irSOM zX)w*=SBWExem_#BNg<;I_B3p43|Y+e4Cw3O>d8L4#d7m<1A8Wu+-Hy(^!vK5B>G&@ z`y62vXqsouy?Ok;)u}Y~34gXBd7J6;cX-`o76SE9F(pusPv9y`_d=WK)T#8<&JV3K ziU&B%C)|Q6*}f6J{xia&N2EZAl5Xr&EKs$T@q}f8JaJu=(wM^6rhmM6Czhq(0u=!# zvSHO?$$Oblk)`(Q?Yt%YjKa1GY*`g>N*R6jdsJY-j))~zo?A8?@6nqy%`li~l{g0l z2AzL=LfjG@YlPo2YPJcHA*ZogApV2f)z*Md`rQO9iXCY}yTkI>^9X06^?M)#K<(@y zp40<9|7BArEW!NZg=K?tydUe2d8(JQ>Trz?u_Dx?9Y?FliaE&eyKkt2w1}vhANen| zuNmBk24M-z>im2xD*8|%F0JG6>@aU~?T_Tl&m&wL9``~Dy)(hTs^m^XMO&WhHRl^% zPGMo*hZ=J7Qi8Iw;!kxHRTTiLKv`u)6>DZWOe|gXf#KTn;o9oa zIsh|M9eZO%ZHxE(E{3M&CQ5eNc4q4F5V2T@oVSUBhMkV7rOkUQb#)hmWMgS#dshcr z8<2;Qm4k)bdp$EJV@-EsIUg%8du>BkcXM|GV^2drS5tdWXJ0o5?I4?Y7ezZ?GnG)M zOh@GqPva184S#=wC|@JDAV>Wuk61sjOR%p|l(SB(w{M6S(hC?JVjdf88y{>D6>6K~ zZ-NMf#D+KrMcSJ|{mo!r(cvyge@(X!A&HSrF)_BNAl2dsr{XBn_AtfJ#Bj&-U{sWD z*$0S!N?aPu*#Qxi1#`_#^odMvY>oqW#%gCK2iGKky|d$rlKedLqSMp8VzOgCrP?NE zJC(pe}2N$JurWvH=#k9lCi?Y2F3u2NAL&xFzmAU??9RHq7>y{j! z+K)luRcV>!vEw<$`Q>pjHOZqNO>0X7;8oD-a>tY^1hfXxQWREK64O``7*m&3SDG+d zXj6-f{a77aSRK(>8d6yqKT`U>1sR=;&MmKj7S}=HjhPb_j-6GJeU*^|mBHhm{HyEZ z&~gvx!twUp_-Vy*5dYh*l?ZeB+9J~oiM}FmC#ZY(tM0eSAcTU4l)qGbDrZ*4MU(z(*G(Au^ zKT`W;q@s7KeQC60Wi)?j0=+cV{&lK&b2@+RbMuecqK&!UojK(C-0=QV&EXPqZ>iyY zvEpp0c57woc;(a4D(Yml^5@3P`S;F?{WV0E``lk){=`*L-vbMafb<^&8!Ib^>aP>m zQ%O}Gcjv()EWksk5TpKI0p)EmvoB`_qbWypqoODU>vT}B=C4LVVCy4 zID4S(1SnHMYS6?X`glAXvcS>Ilpq#4Kj{_j=*%_z#mMkE=X3(Iv4fVaszX+u`n-2q zk1iuPjA}>4Wq)y%bz!r5WD8@oesyr$IrZS_)piQ8k4x&!S-@J&$cTm@_5(t`Zmho` z&R>bH6oP)W)bs1-Su2i`-z|IhFuv8v_zH! zGn5Yo*_J=w4kz0W_~krHk|riOon3xoPOy^O)K= zkQiaFYhDI;Gzi0xhA19o;ZOoz!RSqSuWdw8-*8?RnMDQjK{_lGU z#n2i+60=3%9X8azgDNC@`(@xwtjH~|zu9^Dg*Cp`Inq-az!%Mrgdc|L6O{ zl}SS&o7x{W4^ik!&EUiNK6bu;U5^~YnI*|nglmNCEC{t|pORWVw;n@S)1QyQjEEh2M_07Z zpp&GZ`&WUX!*L4f?cS)fopr!T7O{s%f%`{BYl8zuG?g23#Po!q^&o;6;%?2_NGLA_3C{XKP&IHM`)-Z_PsiAFg-|D>bK z74P$xFK@S=S!fVfKW@y1yl0Ni-4^nb$h#t+V0kk~!mIvKOtoF4xuw6$cT2$T36qK| z0N$hJ2vUg}_|vq*dur_6)^s(IQEuVyK9TL$xn}`H&i!sL8&f9L;vZ>`J8EeCb7B0I z!KHJvu~Ye}ymo6 zM-erb^o~X0E#Kn$r3j8FgvWmGzmVRLl+@;9OAXcEIy9Vb>%49xejhaX0Wr}-0C48I z!1O`(B?we|1NUnr1QChZ#_h`kc!S(#YLbNiZchK~Q2+1HM?biCz~C+O>W>WU1Vb3D zVct$3(f6)!d|1Owf<8{ki4(f;y%aG^@mP)>sS5L3SLH{(7GkpiFRQz#slwFNa;p-g zh(U_q>1i^KSsw6-r!3`6vgAu}vZA8~ZZEGqpxr+d?Nj-{Zw(#P{C~d=7*IJsKYuFg z=42t&_?(JP$w>-|m>%rd-fRq1h2FTk4@G=iBJ6voW`AbhA1Qo@+NGXhpN)U=KCW4~ z=pXF2ROXTGd|S01>pOe52pOYn&3}+!kJmWcZ{xGg(zSJJe6jpXuVC)^vf&Y5mDmi$ zs$hv4Rd=d$(&Jj`YM5cBxWKQO0E;0FkUascAnjkNRozpv4iq>3q57Nh9dY$5wg&PG zz<%+I31QF4Y@>H)!)X38fe+isb{3r6-i3ZvG*tXZm?OQuFEnjdK{%0{b};{+_9fdZ zBYi4%CkQL> zd58U;Nw6ygWzH^0b33zFDL8f`Tb5S;-z#J3gUE@?DA0zbJQ^bT}q3N=Ake5IL#^jZhtkSvHMmdMHY( zq+u|c-@5`0;g42>Q?LwvL1HZWsQ@|#P%4%((9C%Hd=%50zp;c!B<9>4PZdsa5}&fE zZTFo2Wf>^m*HzxV0$r#WlZ)O_c)_`&8bQlRM{ZLqS5nkN=wFTwCJfWCTcsi?z=-o( zy)C&g`w#^J4n8Agv5MJ0oda^5+6FrlyaELne-{FhC-C`@ zzBHL~PqL;ITxo6b*6jT=4ok&oP!X60jww&0FN9;V7BR(KC2#6WM)W`qR?4Y0Y4gMB zY^EGl$vZ0TU;{40EYA|OO{35*$Zo>%Z&Cd_bbC>(C~cBcUp#iq3|H_+0p_y~=nOiW zl!^yWs0L?+(YRX_U^I0>Gu2G&e=`m$5t^fM4=?z8Xu`qv-x3Y`p9=UD(reTixL`~- z|4n}0BO}Ut(!S$#G-1rvgn~hTz`DX@k5S6PVeFRJC3h_UyZOt%>I@4@NnY(;^;@&> F{{pdK*YN-V diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 3bdf70847..5c3d8efa8 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -27227,7 +27227,7 @@ - + @@ -27872,7 +27872,7 @@ - + @@ -27918,9 +27918,22 @@ - + + + + + + + + +

+ z.B. Folding +

+ +
+
@@ -27989,19 +28002,19 @@
- + - + - - + + @@ -28040,12 +28053,12 @@ - - - - - - + + + + + + @@ -28786,8 +28799,8 @@ - - + + @@ -28868,8 +28881,238 @@ - - + + + + + + + + + + + + + + + + + + + + + +

+ ...denn wir müssen sowiso einen globalen Pass machen, und zwar erst spät, wenn das Layout bereits komplett geregelt ist +

+ +
+ + +
+
+ + + + + + + + +

+ TrackHeadWidget::syncSubtrackStartHeight (uint directHeight) +

+ +
+ + + + + + + + +

+ ⤷ kommend von DisplayFrame::sync_and_balance (DisplayEvaluation&) +

+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + +

+ TrackHeadWidget::accommodateOverallHeight(uint overallHeight) +

+ +
+
+ + + + + + + + + + + + + + + + + + + + +
    +
  • + zum Einen habe ich unbemerkt die getLabelHeight() vom Parent zum Child verschleppt. Das ist aber unter dem Strich korrekt, weil jedes Kind wieder mit einem Label beginnt +
  • +
  • + außerdem gibt es da anscheinend im Grid ein zusätzliches Padding, was mir bisher entgangen war +
  • +
+ +
+ +
+ + + + + + + + + + + + +

+ der Expander in der ersten Spalte dient dazu, das TrackHeadWidget auf eine geforderte Nenn-Höhe aufzuspannen. Anscheinend habe ich die Zellen so definiert, daß diese Diskrepanz als spacing zwischen Label, Content und SyncPadding verteilt wird +

+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + +

+ mache hier die vereinfachtende Annahme, daß alle Brackets die gleiche Metrik haben +

+ +
+
+ + + + + + +

+ geprüft mit Screenshot in Gimp. +

+

+ Unter der Einschränkung, daß hier viel Aliasing passiert und das Bild schon relativ klein ist +

+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...der default ist 10, und das erzeugt eine Gehrung nur bis ca 20° +

+ +
+
+ + + +
+
+
@@ -28877,9 +29120,9 @@
- - - + + + @@ -28891,7 +29134,7 @@ - + @@ -29036,7 +29279,7 @@ - + @@ -29314,7 +29557,10 @@ - + + + + @@ -29333,10 +29579,14 @@ - - - - + + + + + + + + @@ -29347,9 +29597,9 @@ + + - - @@ -33977,8 +34227,34 @@ - + + + + + + + + + +

+ ...darüber bin ich auch beim Zeichnen der Connector im StaveBracket gestolpert +

+ +
+
+ + + + + + +

+ sichtbar an der Höhe der Sub-Scope-Verbindungen auf den StaveBrackets +

+ +
+