X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fflexui%2Ffui_ctls.pas;h=69af8af26baff987fa82b7b5bf31ed94b7a02ce5;hb=7da841038d5a4e415324d4441cd397f6664e892d;hp=7969a2617ef52edbaeb113583ae4888d72052413;hpb=6880f8a491a247a34d6afb5508d0a64196a3d26d;p=d2df-sdl.git diff --git a/src/flexui/fui_ctls.pas b/src/flexui/fui_ctls.pas index 7969a26..69af8af 100644 --- a/src/flexui/fui_ctls.pas +++ b/src/flexui/fui_ctls.pas @@ -64,6 +64,7 @@ type mCancel: Boolean; mDefault: Boolean; // colors + mStyleLoaded: Boolean; mCtl4Style: AnsiString; mBackColor: array[0..ClrIdxMax] of TGxRGBA; mTextColor: array[0..ClrIdxMax] of TGxRGBA; @@ -106,6 +107,8 @@ type procedure calcFullClientSize (); + procedure drawFrame (gx, gy, resx, thalign: Integer; const text: AnsiString; dbl: Boolean); + protected var savedClip: TGxRect; // valid only in `draw*()` calls //WARNING! do not call scissor functions outside `.draw*()` API! @@ -121,8 +124,6 @@ type mMaxSize: TLaySize; // maximum size mFlex: Integer; mHoriz: Boolean; - mCanWrap: Boolean; - mLineStart: Boolean; mHGroup: AnsiString; mVGroup: AnsiString; mAlign: Integer; @@ -143,9 +144,7 @@ type //procedure setMaxSize (const sz: TLaySize); inline; // max size; <0: set to some huge value function getFlex (): Integer; inline; // <=0: not flexible function isHorizBox (): Boolean; inline; // horizontal layout for children? - function canWrap (): Boolean; inline; // for horizontal boxes: can wrap children? for child: `false` means 'nonbreakable at *next* ctl' function noPad (): Boolean; inline; // ignore padding in box direction for this control - function isLineStart (): Boolean; inline; // `true` if this ctl should start a new line; ignored for vertical boxes function getAlign (): Integer; inline; // aligning in non-main direction: <0: left/up; 0: center; >0: right/down function getExpand (): Boolean; inline; // expanding in non-main direction: `true` will ignore align and eat all available space function getHGroup (): AnsiString; inline; // empty: not grouped @@ -161,8 +160,6 @@ type property flMaxSize: TLaySize read mMaxSize write mMaxSize; property flPadding: TLaySize read mPadding write mPadding; property flHoriz: Boolean read mHoriz write mHoriz; - property flCanWrap: Boolean read mCanWrap write mCanWrap; - property flLineStart: Boolean read mLineStart write mLineStart; property flAlign: Integer read mAlign write mAlign; property flExpand: Boolean read mExpand write mExpand; property flHGroup: AnsiString read mHGroup write mHGroup; @@ -373,17 +370,9 @@ type function parseProperty (const prname: AnsiString; par: TTextParser): Boolean; override; - procedure drawControl (gx, gy: Integer); override; - end; + procedure layPrepare (); override; // called before registering control in layouter - TUIHLine = class(TUILine) - public - procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser - end; - - TUIVLine = class(TUILine) - public - procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser + procedure drawControl (gx, gy: Integer); override; end; // ////////////////////////////////////////////////////////////////////// // @@ -449,18 +438,42 @@ type // ////////////////////////////////////////////////////////////////////// // TUIButton = class(TUITextLabel) + protected + mSkipLayPrepare: Boolean; + mShadowSize: Integer; + mAddMarkers: Boolean; + mHideMarkers: Boolean; + mPushed: Boolean; + protected procedure setText (const s: AnsiString); override; + procedure cacheStyle (root: TUIStyle); override; + public procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser + procedure layPrepare (); override; // called before registering control in layouter + procedure drawControl (gx, gy: Integer); override; procedure mouseEvent (var ev: THMouseEvent); override; procedure keyEvent (var ev: THKeyEvent); override; end; + // ////////////////////////////////////////////////////////////////////// // + TUIButtonRound = class(TUIButton) + protected + procedure setText (const s: AnsiString); override; + + public + procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser + + procedure layPrepare (); override; // called before registering control in layouter + + procedure drawControl (gx, gy: Integer); override; + end; + // ////////////////////////////////////////////////////////////////////// // TUISwitchBox = class(TUITextLabel) protected @@ -541,6 +554,11 @@ procedure uiUpdateStyles (); procedure uiLayoutCtl (ctl: TUIControl); +// ////////////////////////////////////////////////////////////////////////// // +procedure uiInitialize (); +procedure uiDeinitialize (); + + // ////////////////////////////////////////////////////////////////////////// // var fuiRenderScale: Single = 1.0; @@ -554,6 +572,20 @@ uses utils; +// ////////////////////////////////////////////////////////////////////////// // +procedure uiDeinitialize (); +begin + FreeAndNil(uiContext); +end; + + +procedure uiInitialize (); +begin + if (uiContext <> nil) then raise Exception.Create('FlexUI already initialized'); + uiContext := TGxContext.Create(); +end; + + // ////////////////////////////////////////////////////////////////////////// // var ctlsToKill: array of TUIControl = nil; @@ -636,6 +668,7 @@ begin if (ctl = nil) then exit; lay := TFlexLayouter.Create(); try + if (not ctl.mStyleLoaded) then ctl.updateStyle(); if (ctl is TUITopWindow) and (TUITopWindow(ctl).fitToScreen) then TUITopWindow(ctl).flFitToScreen(); lay.setup(ctl); @@ -816,7 +849,7 @@ begin if (Length(uiTopList) > 0) then uiTopList[High(uiTopList)].blurred(); SetLength(uiTopList, Length(uiTopList)+1); uiTopList[High(uiTopList)] := ctl; - ctl.updateStyle(); + if (not ctl.mStyleLoaded) then ctl.updateStyle(); ctl.activated(); end; @@ -890,20 +923,19 @@ begin actionCB := nil; // layouter interface //mDefSize := TLaySize.Create(64, uiContext.charHeight(' ')); // default size - mDefSize := TLaySize.Create(0, 0); // default size + mDefSize := TLaySize.Create(0, 0); // default size: hidden control mMaxSize := TLaySize.Create(-1, -1); // maximum size mPadding := TLaySize.Create(0, 0); mNoPad := false; mFlex := 0; mHoriz := true; - mCanWrap := false; - mLineStart := false; mHGroup := ''; mVGroup := ''; mStyleId := ''; mCtl4Style := ''; mAlign := -1; // left/top mExpand := false; + mStyleLoaded := false; end; @@ -962,6 +994,7 @@ begin if (stl = nil) then stl := uiFindStyle(''); // default cacheStyle(stl); for ctl in mChildren do ctl.updateStyle(); + mStyleLoaded := true; end; procedure TUIControl.cacheStyle (root: TUIStyle); @@ -1000,9 +1033,7 @@ function TUIControl.getMaxSize (): TLaySize; inline; begin result := mLayMaxSize function TUIControl.getPadding (): TLaySize; inline; begin result := mPadding; end; function TUIControl.getFlex (): Integer; inline; begin result := mFlex; end; function TUIControl.isHorizBox (): Boolean; inline; begin result := mHoriz; end; -function TUIControl.canWrap (): Boolean; inline; begin result := mCanWrap; end; function TUIControl.noPad (): Boolean; inline; begin result := mNoPad; end; -function TUIControl.isLineStart (): Boolean; inline; begin result := mLineStart; end; function TUIControl.getAlign (): Integer; inline; begin result := mAlign; end; function TUIControl.getExpand (): Boolean; inline; begin result := mExpand; end; function TUIControl.getHGroup (): AnsiString; inline; begin result := mHGroup; end; @@ -1019,14 +1050,23 @@ begin end; mWidth := asize.w; mHeight := asize.h; + if (mLayMaxSize.w >= 0) then mWidth := nmin(mWidth, mLayMaxSize.w); + if (mLayMaxSize.h >= 0) then mHeight := nmin(mHeight, mLayMaxSize.h); end; procedure TUIControl.layPrepare (); begin mLayDefSize := mDefSize; - mLayMaxSize := mMaxSize; - if (mLayMaxSize.w >= 0) then mLayMaxSize.w += mFrameWidth*2; - if (mLayMaxSize.h >= 0) then mLayMaxSize.h += mFrameHeight*2; + if (mLayDefSize.w <> 0) or (mLayDefSize.h <> 0) then + begin + mLayMaxSize := mMaxSize; + if (mLayMaxSize.w >= 0) then begin mLayDefSize.w += mFrameWidth*2; mLayMaxSize.w += mFrameWidth*2; end; + if (mLayMaxSize.h >= 0) then begin mLayDefSize.h += mFrameHeight*2; mLayMaxSize.h += mFrameHeight*2; end; + end + else + begin + mLayMaxSize := TLaySize.Create(0, 0); + end; end; @@ -1267,8 +1307,6 @@ begin if (strEquCI1251(prname, 'padding')) then begin mPadding := parsePadding(par); exit; end; if (strEquCI1251(prname, 'nopad')) then begin mNoPad := true; exit; end; // flags - if (strEquCI1251(prname, 'wrap')) then begin mCanWrap := parseBool(par); exit; end; - if (strEquCI1251(prname, 'linestart')) then begin mLineStart := parseBool(par); exit; end; if (strEquCI1251(prname, 'expand')) then begin mExpand := parseBool(par); exit; end; // align if (strEquCI1251(prname, 'align')) then begin mAlign := parseAnyAlign(par); exit; end; @@ -1490,7 +1528,7 @@ begin mParent.getDrawRect(gx, gy, wdt, hgt); if (wdt > 0) and (hgt > 0) then begin - if not intersectRect(gx, gy, wdt, hgt, cgx, cgy, mWidth, mHeight) then + if (not intersectRect(gx, gy, wdt, hgt, cgx, cgy, mWidth, mHeight)) then begin wdt := 0; hgt := 0; @@ -1858,6 +1896,79 @@ end; // ////////////////////////////////////////////////////////////////////////// // +procedure TUIControl.drawFrame (gx, gy, resx, thalign: Integer; const text: AnsiString; dbl: Boolean); +var + cidx, tx, tw: Integer; +begin + if (mFrameWidth < 1) or (mFrameHeight < 1) then exit; + cidx := getColorIndex; + uiContext.color := mFrameColor[cidx]; + case mFrameHeight of + 8: + begin + if dbl then + begin + uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6); + uiContext.rect(gx+5, gy+5, mWidth-10, mHeight-10); + end + else + begin + uiContext.rect(gx+4, gy+4, mWidth-8, mHeight-8); + end; + end; + 14: + begin + if dbl then + begin + uiContext.rect(gx+3, gy+3+3, mWidth-6, mHeight-6-6); + uiContext.rect(gx+5, gy+5+3, mWidth-10, mHeight-10-6); + end + else + begin + uiContext.rect(gx+4, gy+4+3, mWidth-8, mHeight-8-6); + end; + end; + 16: + begin + if dbl then + begin + uiContext.rect(gx+3, gy+3+4, mWidth-6, mHeight-6-8); + uiContext.rect(gx+5, gy+5+4, mWidth-10, mHeight-10-8); + end + else + begin + uiContext.rect(gx+4, gy+4+4, mWidth-8, mHeight-8-8); + end; + end; + else + begin + //TODO! + if dbl then + begin + end + else + begin + end; + end; + end; + + // title + if (Length(text) > 0) then + begin + if (resx < 0) then resx := 0; + tw := uiContext.textWidth(text); + setScissor(mFrameWidth+resx, 0, mWidth-mFrameWidth*2-resx, mFrameHeight); + if (thalign < 0) then tx := gx+resx+mFrameWidth+2 + else if (thalign > 0) then tx := gx+mWidth-mFrameWidth-1-tw + else tx := (gx+resx+mFrameWidth)+(mWidth-mFrameWidth*2-resx-tw) div 2; + uiContext.color := mBackColor[cidx]; + uiContext.fillRect(tx-2, gy, tw+4, mFrameHeight); + uiContext.color := mFrameTextColor[cidx]; + uiContext.drawText(tx, gy, text); + end; +end; + + procedure TUIControl.draw (); var f: Integer; @@ -1866,12 +1977,13 @@ var procedure resetScissor (fullArea: Boolean); inline; begin uiContext.clip := savedClip; - if (fullArea) then + if (fullArea) or ((mFrameWidth = 0) and (mFrameHeight = 0)) then begin setScissor(0, 0, mWidth, mHeight); end else begin + //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, ')'); setScissor(mFrameWidth, mFrameHeight, mWidth-mFrameWidth*2, mHeight-mFrameHeight*2); end; end; @@ -1887,6 +1999,28 @@ begin resetScissor(false); // client area for f := 0 to High(mChildren) do mChildren[f].draw(); resetScissor(true); // full area + if (self is TUISwitchBox) then + begin + uiContext.color := TGxRGBA.Create(255, 0, 0, 255); + //uiContext.fillRect(gx, gy, mWidth, mHeight); + //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, '); sz=(', mWidth, 'x', mHeight, '); clip=', uiContext.clip.toString); + end; + if false and (mId = 'cbtest') then + begin + uiContext.color := TGxRGBA.Create(255, 127, 0, 96); + uiContext.fillRect(gx, gy, mWidth, mHeight); + if (mFrameWidth > 0) and (mFrameHeight > 0) then + begin + uiContext.color := TGxRGBA.Create(255, 255, 0, 96); + uiContext.fillRect(gx+mFrameWidth, gy+mFrameHeight, mWidth-mFrameWidth*2, mHeight-mFrameHeight*2); + end; + end + else if false and (self is TUISwitchBox) then + begin + uiContext.color := TGxRGBA.Create(255, 0, 0, 255); + uiContext.fillRect(gx, gy, mWidth, mHeight); + //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, ')'); + end; drawControlPost(gx, gy); finally uiContext.clip := savedClip; @@ -2045,7 +2179,7 @@ begin inherited; mFitToScreen := true; mFrameWidth := 8; - mFrameHeight := 8; + mFrameHeight := uiContext.charHeight(#184); if (mWidth < mFrameWidth*2+uiContext.iconWinWidth(TGxContext.TWinIcon.Close)) then mWidth := mFrameWidth*2+uiContext.iconWinWidth(TGxContext.TWinIcon.Close); if (mHeight < mFrameHeight*2) then mHeight := mFrameHeight*2; if (Length(mTitle) > 0) then @@ -2062,6 +2196,8 @@ begin mInClose := false; closeCB := nil; mCtl4Style := 'window'; + mDefSize.w := nmax(1, mDefSize.w); + mDefSize.h := nmax(1, mDefSize.h); end; @@ -2118,58 +2254,46 @@ begin uiContext.fillRect(gx, gy, mWidth, mHeight); end; - procedure TUITopWindow.drawControlPost (gx, gy: Integer); var cidx: Integer; - tx, hgt, sbhgt, iwdt: Integer; + hgt, sbhgt, iwdt, ihgt: Integer; begin cidx := getColorIndex; + iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close); if (mDragScroll = TXMode.Drag) then begin - uiContext.color := mFrameColor[cidx]; - uiContext.rect(gx+4, gy+4, mWidth-8, mHeight-8); + //uiContext.color := mFrameColor[cidx]; + drawFrame(gx, gy, iwdt, 0, mTitle, false); end else begin - uiContext.color := mFrameColor[cidx]; - uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6); - uiContext.rect(gx+5, gy+5, mWidth-10, mHeight-10); + ihgt := uiContext.iconWinHeight(TGxContext.TWinIcon.Close); + //uiContext.color := mFrameColor[cidx]; + drawFrame(gx, gy, iwdt, 0, mTitle, true); // vertical scroll bar hgt := mHeight-mFrameHeight*2; if (hgt > 0) and (mFullSize.h > hgt) then begin //writeln(mTitle, ': height=', mHeight-mFrameHeight*2, '; fullsize=', mFullSize.toString); sbhgt := mHeight-mFrameHeight*2+2; - uiContext.fillRect(gx+mWidth-mFrameWidth+1, gy+7, mFrameWidth-3, sbhgt); + uiContext.fillRect(gx+mWidth-mFrameWidth+1, gy+mFrameHeight-1, mFrameWidth-3, sbhgt); hgt += mScrollY; if (hgt > mFullSize.h) then hgt := mFullSize.h; hgt := sbhgt*hgt div mFullSize.h; if (hgt > 0) then begin - setScissor(mWidth-mFrameWidth+1, 7, mFrameWidth-3, sbhgt); - uiContext.darkenRect(gx+mWidth-mFrameWidth+1, gy+7+hgt, mFrameWidth-3, sbhgt, 128); + setScissor(mWidth-mFrameWidth+1, mFrameHeight-1, mFrameWidth-3, sbhgt); + uiContext.darkenRect(gx+mWidth-mFrameWidth+1, gy+mFrameHeight-1+hgt, mFrameWidth-3, sbhgt, 128); end; end; // frame icon - iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close); - setScissor(mFrameWidth, 0, iwdt, 8); + setScissor(mFrameWidth, 0, iwdt, ihgt); uiContext.color := mBackColor[cidx]; - uiContext.fillRect(gx+mFrameWidth, gy, iwdt, 8); + uiContext.fillRect(gx+mFrameWidth, gy, iwdt, ihgt); uiContext.color := mFrameIconColor[cidx]; uiContext.drawIconWin(TGxContext.TWinIcon.Close, gx+mFrameWidth, gy, mInClose); end; - // title - if (Length(mTitle) > 0) then - begin - iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close); - setScissor(mFrameWidth+iwdt, 0, mWidth-mFrameWidth*2-iwdt, 8); - tx := (gx+iwdt)+((mWidth-iwdt)-uiContext.textWidth(mTitle)) div 2; - uiContext.color := mBackColor[cidx]; - uiContext.fillRect(tx-3, gy, uiContext.textWidth(mTitle)+3+2, 8); - uiContext.color := mFrameTextColor[cidx]; - uiContext.drawText(tx, gy, mTitle); - end; // shadow inherited drawControlPost(gx, gy); end; @@ -2260,7 +2384,7 @@ begin begin if (ev.press) then begin - if (ly < 8) then + if (ly < mFrameHeight) then begin uiGrabCtl := self; if (lx >= mFrameWidth) and (lx < mFrameWidth+uiContext.iconWinWidth(TGxContext.TWinIcon.Close)) then @@ -2357,6 +2481,7 @@ begin mCanFocus := false; mHAlign := -1; // left mCtl4Style := 'box'; + mDefSize := TLaySize.Create(-1, -1); end; @@ -2370,7 +2495,7 @@ end; procedure TUIBox.setHasFrame (v: Boolean); begin mHasFrame := v; - if (mHasFrame) then begin mFrameWidth := 8; mFrameHeight := 8; end else begin mFrameWidth := 0; mFrameHeight := 0; end; + if (mHasFrame) then begin mFrameWidth := 8; mFrameHeight := uiContext.charHeight(#184); end else begin mFrameWidth := 0; mFrameHeight := 0; end; if (mHasFrame) then mNoPad := true; end; @@ -2420,26 +2545,29 @@ begin cidx := getColorIndex; uiContext.color := mBackColor[cidx]; uiContext.fillRect(gx, gy, mWidth, mHeight); - if mHasFrame then + if (mHasFrame) then begin // draw frame - uiContext.color := mFrameColor[cidx]; - uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6); - end; - // draw caption - if (Length(mCaption) > 0) then + drawFrame(gx, gy, 0, -1, mCaption, false); + //uiContext.color := mFrameColor[cidx]; + //uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6); + end + else if (Length(mCaption) > 0) then begin + // draw caption if (mHAlign < 0) then xpos := 3 else if (mHAlign > 0) then xpos := mWidth-mFrameWidth*2-uiContext.textWidth(mCaption) else xpos := (mWidth-mFrameWidth*2-uiContext.textWidth(mCaption)) div 2; xpos += gx+mFrameWidth; - setScissor(mFrameWidth+1, 0, mWidth-mFrameWidth-2, 8); - if mHasFrame then + setScissor(mFrameWidth+1, 0, mWidth-mFrameWidth-2, uiContext.textHeight(mCaption)); + { + if (mHasFrame) then begin uiContext.color := mBackColor[cidx]; uiContext.fillRect(xpos-3, gy, uiContext.textWidth(mCaption)+4, 8); end; + } uiContext.color := mFrameTextColor[cidx]; uiContext.drawText(xpos, gy, mCaption); end; @@ -2518,6 +2646,7 @@ begin mCanFocus := false; mNoPad := true; mCtl4Style := 'span'; + mDefSize := TLaySize.Create(-1, -1); end; @@ -2541,6 +2670,7 @@ begin mExpand := true; mCanFocus := false; mCtl4Style := 'line'; + mDefSize := TLaySize.Create(-1, -1); end; @@ -2551,6 +2681,23 @@ begin end; +procedure TUILine.layPrepare (); +begin + inherited layPrepare(); + if (mParent <> nil) then mHoriz := not mParent.mHoriz; + if (mHoriz) then + begin + if (mLayDefSize.w < 0) then mLayDefSize.w := 1; + if (mLayDefSize.h < 0) then mLayDefSize.h := 7; + end + else + begin + if (mLayDefSize.w < 0) then mLayDefSize.w := 7; + if (mLayDefSize.h < 0) then mLayDefSize.h := 1; + end; +end; + + procedure TUILine.drawControl (gx, gy: Integer); var cidx: Integer; @@ -2562,24 +2709,6 @@ begin end; -// ////////////////////////////////////////////////////////////////////////// // -procedure TUIHLine.AfterConstruction (); -begin - inherited; - mHoriz := true; - mDefSize.h := 7; -end; - - -// ////////////////////////////////////////////////////////////////////////// // -procedure TUIVLine.AfterConstruction (); -begin - inherited; - mHoriz := false; - mDefSize.w := 7; -end; - - // ////////////////////////////////////////////////////////////////////////// // procedure TUIStaticText.AfterConstruction (); begin @@ -2590,7 +2719,6 @@ begin mHoriz := true; // nobody cares mHeader := false; mLine := false; - mDefSize.h := uiContext.charHeight(' '); mCtl4Style := 'static'; end; @@ -2685,7 +2813,6 @@ begin mHAlign := -1; mVAlign := 0; mCanFocus := false; - mDefSize := TLaySize.Create(uiContext.textWidth(mText), uiContext.textHeight(mText)); mCtl4Style := 'label'; mLinkId := ''; end; @@ -2851,51 +2978,182 @@ end; procedure TUIButton.AfterConstruction (); begin inherited; - mHAlign := -1; + mHAlign := 0; mVAlign := 0; + mShadowSize := 0; mCanFocus := true; - mDefSize := TLaySize.Create(uiContext.textWidth(mText)+8*2, uiContext.textHeight(mText)+2); + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+uiContext.textWidth('[ ]'), uiContext.textHeight(mText)); mCtl4Style := 'button'; + mSkipLayPrepare := false; + mAddMarkers := false; + mHideMarkers := false; +end; + + +procedure TUIButton.cacheStyle (root: TUIStyle); +var + sz: Integer = 0; +begin + inherited cacheStyle(root); + // shadow size + sz := nmax(0, root.get('shadow-size', 'active', mCtl4Style).asInt(0)); + sz := nmax(sz, root.get('shadow-size', 'disabled', mCtl4Style).asInt(0)); + sz := nmax(sz, root.get('shadow-size', 'inactive', mCtl4Style).asInt(0)); + mShadowSize := sz; + // markers mode + mAddMarkers := root.get('add-markers', 'active', mCtl4Style).asBool(false); + mAddMarkers := mAddMarkers or root.get('add-markers', 'disabled', mCtl4Style).asBool(false); + mAddMarkers := mAddMarkers or root.get('add-markers', 'inactive', mCtl4Style).asBool(false); + // hide markers? + mHideMarkers := root.get('hide-markers', 'active', mCtl4Style).asBool(false); + mHideMarkers := mHideMarkers or root.get('hide-markers', 'disabled', mCtl4Style).asBool(false); + mHideMarkers := mHideMarkers or root.get('hide-markers', 'inactive', mCtl4Style).asBool(false); end; procedure TUIButton.setText (const s: AnsiString); begin inherited setText(s); - mDefSize := TLaySize.Create(uiContext.textWidth(mText)+8*2, uiContext.textHeight(mText)+2); + if (mHideMarkers) then + begin + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+10, uiContext.textHeight(mText)); + end + else if (mAddMarkers) then + begin + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+uiContext.textWidth('[<>]'), uiContext.textHeight(mText)); + end + else + begin + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+uiContext.textWidth('<>'), uiContext.textHeight(mText)); + end; +end; + + +procedure TUIButton.layPrepare (); +var + ods: TLaySize; + ww: Integer; +begin + if (not mSkipLayPrepare) then + begin + ods := mDefSize; + if (ods.w <> 0) or (ods.h <> 0) then + begin + mDefSize := TLaySize.Create(uiContext.textWidth(mText), uiContext.textHeight(mText)); + if (mHideMarkers) then + begin + ww := 10; + end + else if (mAddMarkers) then + begin + if (mDefault) then ww := uiContext.textWidth('[< >]') + else if (mCancel) then ww := uiContext.textWidth('[{ }]') + else ww := uiContext.textWidth('[ ]'); + end + else + begin + ww := nmax(0, uiContext.textWidth('< >')); + ww := nmax(ww, uiContext.textWidth('{ }')); + ww := nmax(ww, uiContext.textWidth('[ ]')); + end; + mDefSize.w += ww+mShadowSize; + mDefSize.h += mShadowSize; + end; + end + else + begin + ods := TLaySize.Create(0, 0); // fpc is dumb! + end; + inherited layPrepare(); + if (not mSkipLayPrepare) then mDefSize := ods; end; procedure TUIButton.drawControl (gx, gy: Integer); var - xpos, ypos: Integer; + wdt, hgt: Integer; + xpos, ypos, xofsl, xofsr{, sofs}: Integer; cidx: Integer; + lch, rch: AnsiChar; + lstr, rstr: AnsiString; begin cidx := getColorIndex; + wdt := mWidth-mShadowSize; + hgt := mHeight-mShadowSize; + if (mPushed) {or (cidx = ClrIdxActive)} then + begin + //sofs := mShadowSize; + gx += mShadowSize; + gy += mShadowSize; + end + else + begin + //sofs := 0; + if (mShadowSize > 0) then + begin + uiContext.darkenRect(gx+mShadowSize, gy+hgt, wdt, mShadowSize, 96); + uiContext.darkenRect(gx+wdt, gy+mShadowSize, mShadowSize, hgt-mShadowSize, 96); + end; + end; + uiContext.color := mBackColor[cidx]; - uiContext.fillRect(gx+1, gy, mWidth-2, mHeight); - uiContext.fillRect(gx, gy+1, 1, mHeight-2); - uiContext.fillRect(gx+mWidth-1, gy+1, 1, mHeight-2); + //setScissor(sofs, sofs, wdt, hgt); + uiContext.fillRect(gx, gy, wdt, hgt); - if (Length(mText) > 0) then + if (mVAlign < 0) then ypos := 0 + else if (mVAlign > 0) then ypos := hgt-uiContext.textHeight(mText) + else ypos := (hgt-uiContext.textHeight(mText)) div 2; + ypos += gy; + + uiContext.color := mTextColor[cidx]; + + if (mHideMarkers) then begin - if (mHAlign < 0) then xpos := 0 - else if (mHAlign > 0) then xpos := mWidth-uiContext.textWidth(mText) - else xpos := (mWidth-uiContext.textWidth(mText)) div 2; + xofsl := 5; + xofsr := 5; + end + else + begin + if (mAddMarkers) then + begin + if (mDefault) then begin lstr := '[< '; rstr := ' >]'; end + else if (mCancel) then begin lstr := '[{ '; rstr := ' }]'; end + else begin lstr := '[ '; rstr := ' ]'; end; + xofsl := uiContext.textWidth(lstr); + xofsr := uiContext.textWidth(rstr); + uiContext.drawText(gx, ypos, lstr); + uiContext.drawText(gx+wdt-uiContext.textWidth(rstr), ypos, rstr); + end + else + begin + xofsl := nmax(0, uiContext.textWidth('< ')); + xofsl := nmax(xofsl, uiContext.textWidth('{ ')); + xofsl := nmax(xofsl, uiContext.textWidth('[ ')); + xofsr := nmax(0, uiContext.textWidth(' >')); + xofsr := nmax(xofsr, uiContext.textWidth(' }')); + xofsr := nmax(xofsr, uiContext.textWidth(' ]')); + if (mDefault) then begin lch := '<'; rch := '>'; end + else if (mCancel) then begin lch := '{'; rch := '}'; end + else begin lch := '['; rch := ']'; end; + uiContext.drawChar(gx, ypos, lch); + uiContext.drawChar(gx+wdt-uiContext.charWidth(rch), ypos, rch); + end; + end; - if (mVAlign < 0) then ypos := 0 - else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText) - else ypos := (mHeight-uiContext.textHeight(mText)) div 2; + if (Length(mText) > 0) then + begin + if (mHAlign < 0) then xpos := 0 + else begin xpos := wdt-xofsl-xofsr-uiContext.textWidth(mText); if (mHAlign = 0) then xpos := xpos div 2; end; + xpos += xofsl; - setScissor(8, 0, mWidth-16, mHeight); - uiContext.color := mTextColor[cidx]; - uiContext.drawText(gx+xpos+8, gy+ypos, mText); + //setScissor(xofsl+sofs, sofs, wdt-xofsl-xofsr, hgt); + uiContext.drawText(gx+xpos, ypos, mText); if (mHotChar <> #0) and (mHotChar <> ' ') then begin uiContext.color := mHotColor[cidx]; - uiContext.drawChar(gx+xpos+8+mHotOfs, gy+ypos, mHotChar); + uiContext.drawChar(gx+xpos+mHotOfs, ypos, mHotChar); end; end; end; @@ -2909,13 +3167,16 @@ begin if (uiGrabCtl = self) then begin ev.eat(); - if (ev = '-lmb') and focused and toLocal(ev.x, ev.y, lx, ly) then + mPushed := toLocal(ev.x, ev.y, lx, ly); + if (ev = '-lmb') and focused and mPushed then begin + mPushed := false; doAction(); end; exit; end; if (ev.eaten) or (ev.cancelled) or (not enabled) or not focused then exit; + mPushed := true; ev.eat(); end; @@ -2935,6 +3196,75 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // +procedure TUIButtonRound.AfterConstruction (); +begin + inherited; + mHAlign := -1; + mVAlign := 0; + mCanFocus := true; + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+8*2, uiContext.textHeight(mText)+2); + mCtl4Style := 'button-round'; + mSkipLayPrepare := true; +end; + + +procedure TUIButtonRound.setText (const s: AnsiString); +begin + inherited setText(s); + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+8*2, uiContext.textHeight(mText)+2); +end; + + +procedure TUIButtonRound.layPrepare (); +var + ods: TLaySize; +begin + ods := mDefSize; + if (ods.w <> 0) or (ods.h <> 0) then + begin + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+8*2, uiContext.textHeight(mText)+2); + end; + inherited layPrepare(); + mDefSize := ods; +end; + + +procedure TUIButtonRound.drawControl (gx, gy: Integer); +var + xpos, ypos: Integer; + cidx: Integer; +begin + cidx := getColorIndex; + + uiContext.color := mBackColor[cidx]; + uiContext.fillRect(gx+1, gy, mWidth-2, mHeight); + uiContext.fillRect(gx, gy+1, 1, mHeight-2); + uiContext.fillRect(gx+mWidth-1, gy+1, 1, mHeight-2); + + if (Length(mText) > 0) then + begin + if (mHAlign < 0) then xpos := 0 + else if (mHAlign > 0) then xpos := mWidth-uiContext.textWidth(mText) + else xpos := (mWidth-uiContext.textWidth(mText)) div 2; + + if (mVAlign < 0) then ypos := 0 + else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText) + else ypos := (mHeight-uiContext.textHeight(mText)) div 2; + + setScissor(8, 0, mWidth-16, mHeight); + uiContext.color := mTextColor[cidx]; + uiContext.drawText(gx+xpos+8, gy+ypos, mText); + + if (mHotChar <> #0) and (mHotChar <> ' ') then + begin + uiContext.color := mHotColor[cidx]; + uiContext.drawChar(gx+xpos+8+mHotOfs, gy+ypos, mHotChar); + end; + end; +end; + + // ////////////////////////////////////////////////////////////////////////// // procedure TUISwitchBox.AfterConstruction (); begin @@ -2943,7 +3273,7 @@ begin mVAlign := 0; mCanFocus := true; mIcon := TGxContext.TMarkIcon.Checkbox; - mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), uiContext.iconMarkHeight(mIcon)); + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), nmax(uiContext.iconMarkHeight(mIcon), uiContext.textHeight(mText))); mCtl4Style := 'switchbox'; mChecked := false; mBoolVar := @mChecked; @@ -2965,7 +3295,7 @@ end; procedure TUISwitchBox.setText (const s: AnsiString); begin inherited setText(s); - mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), uiContext.iconMarkHeight(mIcon)); + mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), nmax(uiContext.iconMarkHeight(mIcon), uiContext.textHeight(mText))); end; @@ -3000,36 +3330,45 @@ end; procedure TUISwitchBox.drawControl (gx, gy: Integer); var - xpos, ypos: Integer; + xpos, ypos, iwdt, dy: Integer; cidx: Integer; begin cidx := getColorIndex; + iwdt := uiContext.iconMarkWidth(mIcon); if (mHAlign < 0) then xpos := 0 - else if (mHAlign > 0) then xpos := mWidth-(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon)) - else xpos := (mWidth-(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon))) div 2; + else if (mHAlign > 0) then xpos := mWidth-(uiContext.textWidth(mText)+3+iwdt) + else xpos := (mWidth-(uiContext.textWidth(mText)+3+iwdt)) div 2; if (mVAlign < 0) then ypos := 0 - else if (mVAlign > 0) then ypos := mHeight-uiContext.iconMarkHeight(mIcon) - else ypos := (mHeight-uiContext.iconMarkHeight(mIcon)) div 2; + else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText) + else ypos := (mHeight-uiContext.textHeight(mText)) div 2; uiContext.color := mBackColor[cidx]; uiContext.fillRect(gx, gy, mWidth, mHeight); uiContext.color := mSwitchColor[cidx]; - uiContext.drawIconMark(mIcon, gx, gy, checked); - - if (mVAlign < 0) then ypos := 0 - else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText) - else ypos := (mHeight-uiContext.textHeight(mText)) div 2; + if (uiContext.iconMarkHeight(mIcon) < uiContext.textHeight(mText)) then + begin + case uiContext.textHeight(mText) of + 14: dy := 2; + 16: dy := 3; + else dy := 1; + end; + uiContext.drawIconMark(mIcon, gx, gy+ypos+uiContext.textHeight(mText)-uiContext.iconMarkHeight(mIcon)-dy, checked); + end + else + begin + uiContext.drawIconMark(mIcon, gx, gy, checked); + end; uiContext.color := mTextColor[cidx]; - uiContext.drawText(gx+xpos+3+uiContext.iconMarkWidth(mIcon), gy+ypos, mText); + uiContext.drawText(gx+xpos+3+iwdt, gy+ypos, mText); if (mHotChar <> #0) and (mHotChar <> ' ') then begin uiContext.color := mHotColor[cidx]; - uiContext.drawChar(gx+xpos+3+uiContext.iconMarkWidth(mIcon)+mHotOfs, gy+ypos, mHotChar); + uiContext.drawChar(gx+xpos+3+iwdt+mHotOfs, gy+ypos, mHotChar); end; end; @@ -3164,13 +3503,11 @@ initialization registerCtlClass(TUIHBox, 'hbox'); registerCtlClass(TUIVBox, 'vbox'); registerCtlClass(TUISpan, 'span'); - registerCtlClass(TUIHLine, 'hline'); - registerCtlClass(TUIVLine, 'vline'); + registerCtlClass(TUILine, 'line'); registerCtlClass(TUITextLabel, 'label'); registerCtlClass(TUIStaticText, 'static'); + registerCtlClass(TUIButtonRound, 'round-button'); registerCtlClass(TUIButton, 'button'); registerCtlClass(TUICheckBox, 'checkbox'); registerCtlClass(TUIRadioBox, 'radiobox'); - - uiContext := TGxContext.Create(); end.