diff options
author | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-09-05 08:18:24 +0000 |
---|---|---|
committer | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-09-05 08:18:24 +0000 |
commit | 0cede94a92cf6c1cb0b46a1f1782ae2715fbd862 (patch) | |
tree | 26f01db17f7abf1a38d403ab1d0e61f352ebec28 /src/gui | |
parent | 4ef91ca61a1cac4918fbe40c1550a84819744404 (diff) | |
download | fpGUI-0cede94a92cf6c1cb0b46a1f1782ae2715fbd862.tar.xz |
* Added some painting fixes to the Treeview. Also added a few new properties.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/gui_tree.pas | 178 |
1 files changed, 123 insertions, 55 deletions
diff --git a/src/gui/gui_tree.pas b/src/gui/gui_tree.pas index 586745b8..af86a945 100644 --- a/src/gui/gui_tree.pas +++ b/src/gui/gui_tree.pas @@ -5,6 +5,10 @@ unit gui_tree; { TODO: * Lots!! + * Columns need to be reworked. We don't want coluns per node levels. Instead + we want a main column covering the tree. Then extra columns for user + text and data.gui_tree + * Implement event handlers the user can hook into and do custom drawing. WARNING: This is still under heavy development! Do NOT use. } @@ -34,13 +38,11 @@ type private FFirstSubNode: TfpgTreeNode; // the subnodes - for list implementation FLastSubNode: TfpgTreeNode; - FText: string; FParent: TfpgTreeNode; FNext: TfpgTreeNode; FPrev: TfpgTreeNode; FCollapsed: boolean; - FSelColor: TfpgColor; FTextColor: TfpgColor; FSelTextColor: TfpgColor; @@ -102,12 +104,15 @@ type TfpgTreeview = class(TfpgWidget) private FRootNode: TfpgTreeNode; + FScrollWheelDelta: integer; FSelection: TfpgTreeNode; // currently selected node FDefaultColumnWidth: word; FFirstColumn: PfpgTreeColumnWidth; // the list for column widths FFont: TfpgFont; FShowColumns: boolean; FHScrollbar: TfpgScrollbar; + FTreeLineColor: TfpgColor; + FTreeLineStyle: TfpgLineStyle; FVScrollbar: TfpgScrollbar; // FImageList : TfpgImageList; // imagelist to be implemented in the future FShowImages : boolean; @@ -127,6 +132,8 @@ type procedure SetSelection(const AValue: TfpgTreeNode); procedure SetShowColumns(const AValue: boolean); procedure SetShowImages(const AValue: boolean); + procedure SetTreeLineColor(const AValue: TfpgColor); + procedure SetTreeLineStyle(const AValue: TfpgLineStyle); function VisibleWidth: integer; function VisibleHeight: integer; function GetNodeHeightSum: integer; @@ -148,8 +155,10 @@ type procedure HandleLMouseDown(x, y: integer; shiftstate: TShiftState); override; procedure HandleDoubleClick(x, y: integer; button: word; shiftstate: TShiftState); override; procedure HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); override; + procedure HandleMouseScroll(x, y: integer; shiftstate: TShiftState; delta: smallint); override; procedure HandleShow; override; procedure HandlePaint; override; + procedure DrawHeader(ACol: integer; ARect: TfpgRect; AFlags: integer); virtual; procedure DoChange; virtual; procedure DoExpand(ANode: TfpgTreeNode); virtual; function NextVisualNode(ANode: TfpgTreeNode): TfpgTreeNode; @@ -168,6 +177,9 @@ type property ShowColumns: boolean read FShowColumns write SetShowColumns default False; property FontDesc: string read GetFontDesc write SetFontDesc; property DefaultColumnWidth: word read FDefaultColumnWidth write SetDefaultColumnWidth; + property TreeLineColor: TfpgColor read FTreeLineColor write SetTreeLineColor; + property TreeLineStyle: TfpgLineStyle read FTreeLineStyle write SetTreeLineStyle; + property ScrollWheelDelta: integer read FScrollWheelDelta write FScrollWheelDelta; property OnChange: TNotifyEvent read FOnChange write FOnChange; property OnExpand: TfpgTreeExpandEvent read FOnExpand write FOnExpand; end; @@ -664,6 +676,22 @@ begin end; end; +procedure TfpgTreeview.SetTreeLineColor(const AValue: TfpgColor); +begin + if FTreeLineColor = AValue then + Exit; //==> + FTreeLineColor := AValue; + RePaint; +end; + +procedure TfpgTreeview.SetTreeLineStyle(const AValue: TfpgLineStyle); +begin + if FTreeLineStyle = AValue then + Exit; //==> + FTreeLineStyle := AValue; + RePaint; +end; + function TfpgTreeview.VisibleWidth: integer; begin if GetNodeHeightSum * (GetNodeHeight) > Height - 2 then @@ -1018,53 +1046,28 @@ begin r.SetRect(0, 0, Width, Height); Canvas.DrawRectangle(r); // border - if ShowColumns then // draw the column header? + {$Note Columns need to be redesigned completely } + if ShowColumns then begin - r.SetRect(1, 1, VisibleWidth, FColumnHeight); - Canvas.SetClipRect(r); - Canvas.SetColor(clHilite1); - Canvas.DrawLine(1, 1, VisibleWidth, 1); - Canvas.DrawLine(1, 1, 1, FColumnHeight - 1); - Canvas.SetColor(clHilite2); - Canvas.DrawLine(1, 2, VisibleWidth - 1, 2); - Canvas.DrawLine(2, 2, FColumnHeight - 1, 2); - Canvas.SetColor(clShadow2); - Canvas.DrawLine(1, FColumnHeight, VisibleWidth, FColumnHeight); - Canvas.DrawLine(VisibleWidth, 1, VisibleWidth, FColumnHeight); - Canvas.SetColor(clShadow1); - Canvas.DrawLine(2, FColumnHeight - 1, VisibleWidth - 1, FColumnHeight - 1); - Canvas.DrawLine(VisibleWidth - 1, 2, VisibleWidth - 1, FColumnHeight - 1); - Canvas.SetColor(clGridHeader); - Canvas.FillRectangle(3, 3, VisibleWidth - 4, FColumnHeight - 4); - Canvas.SetColor(clWidgetFrame); - - w := 0; - r.SetRect(3, 2, VisibleWidth - 4, FColumnHeight - 2); - Canvas.SetClipRect(r); - for i := 1 to rootnode.getMaxDepth - 1 do - begin - w := w + GetColumnWidth(i); - Canvas.DrawLine(w - FXOffset, 2, w - FXOffset, FColumnHeight - 1); - end; - Canvas.SetColor(clShadow1); - w := 0; - for i := 1 to rootnode.getMaxDepth - 1 do - begin - w := w + GetColumnWidth(i); - Canvas.DrawLine(w - 1 - FXOffset, 3, w - 1 - FXOffset, FColumnHeight - 2); - end; - Canvas.SetColor(clHilite2); - w := 0; - for i := 1 to rootnode.getMaxDepth - 1 do + // Drawing column headers + r.SetRect(1, 1, 0, FColumnHeight); + for col := 1 to rootnode.getMaxDepth - 1 do begin - w := w + GetColumnWidth(i); - Canvas.DrawLine(w + 1 - FXOffset, 3, w + 1 - FXOffset, FColumnHeight - 2); + r.Width := GetColumnWidth(col); + DrawHeader(col, r, 0); + inc(r.Left, r.Width); + if r.Left >= VisibleWidth then + Break; // small optimization. Don't draw what we can't see end; + // Fill remainder of the client area with one big header + r.width := VisibleWidth - r.Left + 1; + DrawHeader(col+1, r, 0); end; - + + // Calculate the client area used for nodes and lines if ShowColumns then begin - r.SetRect(1, 1 + FColumnHeight, VisibleWidth, VisibleHeight); // drawing rectangle for nodes and lines + r.SetRect(1, 1 + FColumnHeight, VisibleWidth, VisibleHeight); col := FColumnHeight; end else @@ -1136,53 +1139,71 @@ begin } Canvas.DrawString(w - FXOffset + 1, ACenterPos - FFont.Ascent div 2, h.text); end; { if/else } - Canvas.SetColor(clText1); + + Canvas.SetLineStyle(1, FTreeLineStyle); if h.Count > 0 then // subnodes? begin + // subnode rectangle around the "+" or "-" + Canvas.SetColor(FTreeLineColor); + Canvas.SetLineStyle(1, lsSolid); // rectangle is always solid line style Canvas.DrawRectangle(w - FXOffset - GetColumnWidth(i1) div 2 - 3, ACenterPos - 3, 9, 9); - if h.Collapsed then // draw a "+" + Canvas.SetColor(clText1); + + if h.Collapsed then begin - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 - 1, ACenterPos + 1, w - FXOffset - GetColumnWidth(i1) div 2 + 3, ACenterPos + 1); + // draw a "+" + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 - 1, ACenterPos + 1, w - FXOffset - GetColumnWidth(i1) div 2 + 4, ACenterPos + 1); Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - 1, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos + 3); end else - begin // draw a "-" - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 - 1, ACenterPos + 1, w - FXOffset - GetColumnWidth(i1) div 2 + 3, ACenterPos + 1); + begin + // draw a "-" + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 - 1, ACenterPos + 1, w - FXOffset - GetColumnWidth(i1) div 2 + 4, ACenterPos + 1); end; + + Canvas.SetLineStyle(1, FTreeLineStyle); end else begin - Canvas.SetColor(clText1); - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos + 1, w - FXOffset - 3, ACenterPos + 1); + // short horizontal line for each node + Canvas.SetColor(FTreeLineColor); + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos + 1, w - FXOffset - 1, ACenterPos + 1); end; + Canvas.SetColor(FTreeLineColor); if h.prev <> nil then begin // line up to the previous node if h.prev.count > 0 then begin + // take the previous subnode rectangle in account if h.count > 0 then - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - 4, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 6) + // we have a subnode rectangle + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - 4, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - (SpaceToVisibleNext(h.prev) * GetNodeHeight) + 5) else - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 6) + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - (SpaceToVisibleNext(h.prev) * GetNodeHeight) + 5); end else begin + // previous node has no subnodes if h.count > 0 then - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - 3, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 2) + // we have a subnode rectangle + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - 3, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 1) else - Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 2); + Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - SpaceToVisibleNext(h.prev) * GetNodeHeight + 1); end; end else begin if h.count > 0 then + // take the subnode rectangle in account Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1,ACenterPos - 3, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - GetNodeHeight div 2 + 3) else Canvas.DrawLine(w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos, w - FXOffset - GetColumnWidth(i1) div 2 + 1, ACenterPos - GetNodeHeight div 2 + 3); end; end; - if AVisibleHeight > ACenterPos + GetNodeHeight then + + if AVisibleHeight > (ACenterPos + GetNodeHeight) then begin if h.count > 0 then begin @@ -1235,12 +1256,56 @@ begin Canvas.EndDraw; end; +procedure TfpgTreeview.DrawHeader(ACol: integer; ARect: TfpgRect; + AFlags: integer); +var + s: string; + r: TfpgRect; + x: integer; +begin + // Here we can implement a head style check + Canvas.DrawButtonFace(ARect, [btnIsEmbedded]); +{ + r := ARect; + InflateRect(r, -2, -2); + Canvas.SetClipRect(r); // text cannot oversheet header border + + Canvas.SetTextColor(clText1); + s := GetHeaderText(ACol); + x := (ARect.Left + (ARect.Width div 2)) - (FHeaderFont.TextWidth(s) div 2); + if x < 1 then + x := 1; + fpgStyle.DrawString(Canvas, x, ARect.Top+1, s, Enabled); +} +end; + procedure TfpgTreeview.HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); begin inherited HandleKeyPress(keycode, shiftstate, consumed); end; +procedure TfpgTreeview.HandleMouseScroll(x, y: integer; + shiftstate: TShiftState; delta: smallint); +begin + inherited HandleMouseScroll(x, y, shiftstate, delta); + if delta > 0 then + begin + inc(FYOffset, FScrollWheelDelta); + if FYOffset > VisibleHeight then + FYOffset := VisibleHeight; + end + else + begin + dec(FYOffset, FScrollWheelDelta); + if FYOffset < 0 then + FYOffset := 0; + end; + + UpdateScrollbars; + RePaint; +end; + procedure TfpgTreeview.DoChange; begin if Assigned(FOnChange) then @@ -1380,11 +1445,14 @@ begin FVScrollbar.SliderSize := 0.2; FBackgroundColor := clListBox; + FTreeLineColor := clShadow1; //clText1; + FTreeLineStyle := lsSolid; FFocusable := True; FMoving := False; FXOffset := 0; FYOffset := 0; FColumnHeight := FFont.Height + 2; + FScrollWheelDelta := 15; end; procedure TfpgTreeview.SetColumnWidth(AIndex, AWidth: word); |