diff options
Diffstat (limited to 'src/gui/fpg_tab.pas')
-rw-r--r-- | src/gui/fpg_tab.pas | 843 |
1 files changed, 580 insertions, 263 deletions
diff --git a/src/gui/fpg_tab.pas b/src/gui/fpg_tab.pas index d656ad3a..9999fa83 100644 --- a/src/gui/fpg_tab.pas +++ b/src/gui/fpg_tab.pas @@ -1,7 +1,7 @@ { fpGUI - Free Pascal GUI Toolkit - Copyright (C) 2006 - 2008 See the file AUTHORS.txt, included in this + Copyright (C) 2006 - 2010 See the file AUTHORS.txt, included in this distribution, for details of the copyright. See the file COPYING.modifiedLGPL, included in this distribution, @@ -22,10 +22,10 @@ unit fpg_tab; { TODO: * Tab Styles (tab, button, flat button, angled) - * Tab Position (top, bottom, left, right) * Better keyboard support * Focus rectangle drawn on tabs itself * FindNextPage() must be implemented + * Popup menu for tab selection. Should occur with RClick on tabs. } interface @@ -36,38 +36,48 @@ uses fpg_base, fpg_main, fpg_widget, - fpg_button; + fpg_button, + fpg_menu; type // forward declaration TfpgPageControl = class; TfpgTabStyle = (tsTabs, tsButtons, tsFlatButtons); - TfpgTabPosition = (tpTop, tpBottom{, tpLeft, tpRight}); + TfpgTabPosition = (tpTop, tpBottom, tpLeft, tpRight, tpNone); + TfpgTabOption = (to_PMenuClose, to_PMenuShowAvailTabs); + + TfpgTabOptions = set of TfpgTabOption; TfpgTabSheet = class(TfpgWidget) private + FPageControl: TfpgPageControl; FText: string; + FTabVisible: boolean; function GetPageControl: TfpgPageControl; function GetPageIndex: Integer; function GetText: string; procedure SetPageIndex(const AValue: Integer); procedure SetText(const AValue: string); + procedure SetPageControl(APageControl: TfpgPageControl); protected procedure HandlePaint; override; + procedure SetName(const NewName: TComponentName); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure AfterConstruction; override; property PageIndex: Integer read GetPageIndex write SetPageIndex; - property PageControl: TfpgPageControl read GetPageControl; + property PageControl: TfpgPageControl read FPageControl write SetPageControl; + property TabVisible: boolean read FTabVisible write FTabVisible; published property Text: string read GetText write SetText; + property OnPaint; end; TTabSheetChange = procedure(Sender: TObject; NewActiveSheet: TfpgTabSheet) of object; + TTabSheetClosing = procedure(Sender: TObject; ATabSheet: TfpgTabSheet) of object; TfpgPageControl = class(TfpgWidget) @@ -76,28 +86,33 @@ type FActivePage: TfpgTabSheet; FMargin: integer; FFixedTabWidth: integer; + FFixedTabHeight: Integer; + FOnClosingTabSheet: TTabSheetClosing; FPages: TList; FActivePageIndex: integer; FOnChange: TTabSheetChange; - FRightButton: TfpgButton; - FLeftButton: TfpgButton; - FFirstTabButton: TfpgTabSheet; + FRightButton: TfpgButton; // bottom/right + FLeftButton: TfpgButton; // left/top + FFirstTabButton: TfpgTabSheet; // when tabs don't fit in screen this is the first button on screen when tabs are scrolled FSortPages: boolean; FStyle: TfpgTabStyle; FTabPosition: TfpgTabPosition; + FPopupMenu: TfpgPopupMenu; + FTabOptions: TfpgTabOptions; function GetActivePageIndex: integer; function GetPage(AIndex: integer): TfpgTabSheet; function GetPageCount: Integer; - procedure InsertPage(const APage: TfpgTabSheet); + procedure InsertPage(const APage: TfpgTabSheet; SuppressOnChangeEvent: boolean = False); procedure RemovePage(const APage: TfpgTabSheet); procedure SetActivePageIndex(const AValue: integer); procedure SetActivePage(const AValue: TfpgTabSheet); function MaxButtonWidthSum: integer; - function MaxButtonHeight: integer; + function MaxButtonHeightSum: integer; function MaxButtonWidth: integer; function ButtonHeight: integer; function ButtonWidth(AText: string): integer; procedure SetFixedTabWidth(const AValue: integer); + procedure SetFixedTabHeight(const AValue: integer); function GetTabText(AText: string): string; procedure LeftButtonClick(Sender: TObject); procedure RightButtonClick(Sender: TObject); @@ -105,14 +120,17 @@ type procedure SetSortPages(const AValue: boolean); procedure SetStyle(const AValue: TfpgTabStyle); procedure SetTabPosition(const AValue: TfpgTabPosition); - procedure DoChange(ATabSheet: TfpgTabSheet); + procedure DoPageChange(ATabSheet: TfpgTabSheet); + procedure DoTabSheetClosing(ATabSheet: TfpgTabSheet); function DrawTab(const rect: TfpgRect; const Selected: Boolean = False; const Mode: Integer = 1): TfpgRect; + procedure pmCloseTab(Sender: TObject); protected procedure OrderSheets; // currently using bubblesort procedure RePaintTitles; virtual; procedure HandlePaint; override; procedure HandleShow; override; procedure HandleLMouseUp(x, y: integer; shiftstate: TShiftState); override; + procedure HandleRMouseUp(x, y: integer; shiftstate: TShiftState); override; procedure HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); override; public constructor Create(AOwner: TComponent); override; @@ -123,10 +141,14 @@ type property ActivePage: TfpgTabSheet read FActivePage write SetActivePage; property Pages[AIndex: integer]: TfpgTabSheet read GetPage; property OnChange: TTabSheetChange read FOnChange write FOnChange; + property OnClosingTabSheet: TTabSheetClosing read FOnClosingTabSheet write FOnClosingTabSheet; published property ActivePageIndex: integer read GetActivePageIndex write SetActivePageIndex; property BackgroundColor; property FixedTabWidth: integer read FFixedTabWidth write SetFixedTabWidth default 0; + property FixedTabHeight: integer read FFixedTabHeight write SetFixedTabHeight default 21; + property Hint; + property Options: TfpgTabOptions read FTabOptions write FTabOptions; property ParentShowHint; property ShowHint; property SortPages: boolean read FSortPages write SetSortPages default False; @@ -134,6 +156,7 @@ type property TabOrder; property TabPosition: TfpgTabPosition read FTabPosition write SetTabPosition default tpTop; property TextColor; + property OnShowHint; end; @@ -197,30 +220,50 @@ begin Canvas.Clear(FBackgroundColor); end; +procedure TfpgTabSheet.SetName(const NewName: TComponentName); +var + old: String; +begin + old := NewName; + inherited SetName(NewName); + if (csDesigning in ComponentState) then + begin + if (Text = '') or (Text = old) then + Text := NewName; + end; +end; + constructor TfpgTabSheet.Create(AOwner: TComponent); begin inherited Create(AOwner); FText := ''; + FTabVisible:= True; FFocusable := True; FBackgroundColor := Parent.BackgroundColor; FTextColor := Parent.TextColor; FIsContainer := True; + if (AOwner <> nil) and (AOwner is TfpgPageControl) then + begin + FPageControl:=TfpgPageControl(AOwner); + FPageControl.InsertPage(self, True); + end; end; destructor TfpgTabSheet.Destroy; begin - if Owner is TfpgPageControl then - TfpgPageControl(Owner).RemovePage(self); + if FPageControl <> nil then + FPageControl.RemovePage(self); inherited Destroy; end; -procedure TfpgTabSheet.AfterConstruction; +procedure TfpgTabSheet.SetPageControl(APageControl: TfpgPageControl); begin - inherited AfterConstruction; - if Owner is TfpgPageControl then - TfpgPageControl(Owner).InsertPage(self); + FPageControl := APageControl; + if APageControl <> nil then + FPageControl.InsertPage(Self); end; + { TfpgPageControl } function TfpgPageControl.GetActivePageIndex: integer; @@ -240,27 +283,55 @@ begin Result := FPages.Count; end; -procedure TfpgPageControl.InsertPage(const APage: TfpgTabSheet); +procedure TfpgPageControl.InsertPage(const APage: TfpgTabSheet; SuppressOnChangeEvent: boolean = False); begin if FPages.IndexOf(APage) <> -1 then Exit; //==> The page has already been added. FPages.Add(APage); - ActivePage := APage; + { TODO: This behaviour could maybe be controlled by a Options property } + if FPages.Count=1 then + begin + if SuppressOnChangeEvent then + Loading; + ActivePage := APage; + if SuppressOnChangeEvent then + Loaded; + end; end; procedure TfpgPageControl.RemovePage(const APage: TfpgTabSheet); +var + i: integer; begin if APage = nil then - Exit; - FPages.Remove(APage); - {$Note This still needs to be fixed.} - if APage = FActivePage then + Exit; // ==> + if FPages.Count =0 then + Exit; // ==> + + if FPages.Count > 1 then + begin + i:=FPages.IndexOf(APage); + FPages.Remove(APage); + APage.PageControl:=nil; + APage.Visible:=false; + if i = ActivePageIndex then + begin + if i > FPages.Count-1 then + ActivePage:=TfpgTabSheet(FPages.Last) + else if i = 0 then + ActivePage:= TfpgTabSheet(FPages.First) + else + ActivePage:=TfpgTabSheet(FPages[i]); + end + else if i < ActivePageIndex then + ActivePage:=TfpgTabSheet(Pages[i-1]); + end + else begin -// FActivePage := FindNextPage(APage, True); -// if FPages.Count > 0 then - ActivePage := TfpgTabSheet(FPages.First); -// else -// ActivePage := nil; + FPages.Remove(APage); + APage.PageControl := nil; + APage.Visible := False; + ActivePage := nil; end; end; @@ -278,8 +349,10 @@ begin Exit; //==> FActivePage := AValue; ActiveWidget := AValue; - FActivePageIndex := FPages.IndexOf(AValue); + if AValue <> nil then + FActivePageIndex := FPages.IndexOf(AValue); RePaint; + DoPageChange(FActivePage); end; function TfpgPageControl.MaxButtonWidthSum: integer; @@ -297,28 +370,38 @@ begin end; end; -function TfpgPageControl.MaxButtonHeight: integer; +function TfpgPageControl.MaxButtonHeightSum: integer; begin result := PageCount * ButtonHeight; end; function TfpgPageControl.MaxButtonWidth: integer; var - t: TfpgTabSheet; - i: integer; + t: TfpgTabSheet; + i: integer; begin Result := 0; - for i := 0 to FPages.Count-1 do + if FixedTabWidth > 0 then begin - t := TfpgTabSheet(FPages[i]); - if ButtonWidth(t.Text) > Result then - Result := ButtonWidth(t.Text); + Result := FixedTabWidth; + end + else + begin + for i := 0 to FPages.Count-1 do + begin + t := TfpgTabSheet(FPages[i]); + if ButtonWidth(t.Text) > Result then + Result := ButtonWidth(t.Text); + end; end; end; function TfpgPageControl.ButtonHeight: integer; begin - Result := FRightButton.Height; + if FFixedTabHeight > 0 then + result := FFixedTabHeight + else + result := FFont.Height + 10; { TODO: correct this } end; function TfpgPageControl.ButtonWidth(AText: string): integer; @@ -340,6 +423,17 @@ begin end; end; +procedure TfpgPageControl.SetFixedTabHeight(const AValue: integer); +begin + if FFixedTabHeight = AValue then + Exit; //==> + if AValue > 5 then + begin + FFixedTabHeight := AValue; + RePaint; + end; +end; + function TfpgPageControl.GetTabText(AText: string): string; var s, s1: string; @@ -360,7 +454,7 @@ begin inc(i); end; if FFont.TextWidth(s1) > (FFixedTabWidth-10) then - Delete(s1, length(s1), 1); {$Note This must become a UTF8 function} + UTF8Delete(s1, UTF8Length(s1), 1); if Length(s1) > 0 then s1 := Trim(s1); Result := s1; @@ -424,12 +518,26 @@ begin RePaint; end; -procedure TfpgPageControl.DoChange(ATabSheet: TfpgTabSheet); +procedure TfpgPageControl.DoPageChange(ATabSheet: TfpgTabSheet); begin + if (csLoading in ComponentState) then + Exit; + if (csDesigning in ComponentState) then + Exit; if Assigned(FOnChange) then FOnChange(self, ATabSheet); end; +procedure TfpgPageControl.DoTabSheetClosing(ATabSheet: TfpgTabSheet); +begin + if (csLoading in ComponentState) then + Exit; + if (csDesigning in ComponentState) then + Exit; + if Assigned(FOnClosingTabSheet) then + FOnClosingTabSheet(self, ATabSheet); +end; + function TfpgPageControl.DrawTab(const rect: TfpgRect; const Selected: Boolean = False; const Mode: Integer = 1): TfpgRect; var r: TfpgRect; @@ -443,36 +551,119 @@ begin end; if Mode = 2 then - r.Height := r.Height - 1; + r.Height -= 1; Canvas.SetColor(clWindowBackground); - Canvas.FillRectangle(r.Left, r.Top, r.Width, r.Height-2); - Canvas.SetColor(clHilite2); - Canvas.DrawLine(r.Left, r.Bottom-2, r.Left, r.Top+2); - Canvas.DrawLine(r.Left, r.Top+2, r.Left+2, r.Top); - Canvas.DrawLine(r.Left+2, r.Top, r.Right-1, r.Top); - Canvas.SetColor(clShadow1); - Canvas.DrawLine(r.Right-1, r.Top+1, r.Right-1, r.Bottom-1); - Canvas.SetColor(clShadow2); - Canvas.DrawLine(r.Right-1, r.Top+1, r.Right, r.Top+2); - Canvas.DrawLine(r.Right, r.Top+2, r.Right, r.Bottom-1); + case TabPosition of + tpTop: + begin + Canvas.FillRectangle(r.Left, r.Top, r.Width, r.Height-2); // fill tab background + Canvas.SetColor(clHilite2); + Canvas.DrawLine(r.Left, r.Bottom-2 , r.Left, r.Top+2); // left edge + Canvas.DrawLine(r.Left, r.Top+2 , r.Left+2, r.Top); // left rounder edge + Canvas.DrawLine(r.Left+2, r.Top, r.Right-1, r.Top); // top edge + Canvas.SetColor(clShadow1); + Canvas.DrawLine(r.Right-1, r.Top+1, r.Right-1, r.Bottom-1); // right inner edge + Canvas.SetColor(clShadow2); + Canvas.DrawLine(r.Right-1, r.Top+1, r.Right, r.Top+2); // right rounded edge (1px) + Canvas.DrawLine(r.Right, r.Top+2, r.Right, r.Bottom-1); // right outer edge + end; + + tpBottom: + begin + Canvas.FillRectangle(r.Left, r.Top, r.Width-2, r.Height-2); // fill tab background + Canvas.SetColor(clHilite2); + Canvas.DrawLine(r.Left, r.Top, r.Left, r.Bottom-1); // left edge + Canvas.SetColor(clShadow2); + Canvas.DrawLine(r.Left+2, r.Bottom, r.Right-1, r.Bottom); // bottom outer edge + Canvas.SetColor(clShadow1); + Canvas.DrawLine(r.Right-1, r.Bottom-1, r.Right-1, r.Top+1); // right inner edge + Canvas.DrawLine(r.Left+1, r.Bottom-1, r.Right-1, r.Bottom-1);// bottom inner edge + Canvas.SetColor(clShadow2); + Canvas.DrawLine(r.Right-1, r.Bottom-1, r.Right, r.Bottom-2); // right rounded edge (1px) + Canvas.DrawLine(r.Right, r.Bottom-2, r.Right, r.Top+1); // right outer edge + end; + + tpLeft: + begin + if Mode = 2 then + begin + r.Width := r.Width - 1; + r.Height := r.Height + 2; + end; + with Canvas do + begin + FillRectangle(r.Left, r.Top, r.Width, r.Height-2); + SetColor(clHilite2); + DrawLine(r.Left, r.Bottom-2, r.Left, r.Top+2); + DrawLine(r.Left, r.Top+2, r.Left+2, r.Top); + DrawLine(r.Left+2, r.Top, r.Right-1, r.Top); + SetColor(clShadow1); + DrawLine(r.Left+2, r.Bottom-1, r.Right-1, r.Bottom-1); + SetColor(clShadow2); + DrawLine(r.Left+1, r.Bottom-1, r.Left+3, r.Bottom); + DrawLine(r.Left+2, r.Bottom, r.Right, r.Bottom); + end; + end; + + tpRight: + begin + if Mode = 2 then + begin + r.Width := r.Width + 1; + r.Height := r.Height + 2; + end; + with Canvas do + begin + FillRectangle(r.Left, r.Top, r.Width, r.Height-2); + SetColor(clHilite2); + DrawLine(r.Left+1, r.Top, r.Right-2, r.Top); + SetColor(clShadow1); + DrawLine(r.Right-2,r.Top,r.Right-1,r.Top+1); + DrawLine(r.Left+2, r.Bottom-1, r.Right-2, r.Bottom-1); + DrawLine(r.Right-3, r.Bottom-1, r.Right-1, r.Bottom-3); + DrawLine(r.Right-1, r.Bottom-3, r.Right-1, r.Top); + SetColor(clShadow2); + DrawLine(r.Left+2,r.Bottom,r.Right-3, r.Bottom); + DrawLine(r.Right-3, r.Bottom, r.Right, r.Bottom-3); + DrawLine(r.Right, r.Top+2, r.Right, r.Bottom-2); + end; + end; + end; { case } +end; + +procedure TfpgPageControl.pmCloseTab(Sender: TObject); +var + ts: TfpgTabSheet; +begin + ts := ActivePage; + if ts = nil then + Exit; + RemovePage(ts); + DoTabSheetClosing(ts); + ts.Free; end; procedure TfpgPageControl.OrderSheets; begin FPages.Sort(@SortCompare); + FActivePageIndex := FPages.IndexOf(ActivePage); end; procedure TfpgPageControl.RePaintTitles; +const + TabHeight = 21; var - r: TfpgRect; + TabW, TabH: Integer; r2: TfpgRect; r3: TfpgRect; h: TfpgTabSheet; lp: integer; toffset: integer; + TextLeft, TextTop: Integer; dx: integer; lTxtFlags: TFTextFlags; + ActivePageVisible: Boolean; begin if not HasHandle then Exit; //==> @@ -480,179 +671,285 @@ begin if PageCount = 0 then Exit; //==> + TabW:=FixedTabWidth; + TabH:=FixedTabHeight; + ActivePageVisible := false; + If TabH = 0 then + TabH := TabHeight; h := TfpgTabSheet(FPages.First); if h = nil then - Exit; + Exit; //==> + Canvas.BeginDraw; Canvas.SetTextColor(TextColor); - lTxtFlags := TextFlagsDflt; + lTxtFlags := []; if not Enabled then Include(lTxtFlags, txtDisabled); + + if TabPosition in [tpTop, tpBottom] then + begin + if MaxButtonWidthSum > (Width-(FMargin*2)) then + begin + if FFirstTabButton = nil then + FFirstTabButton := h + else + h := FFirstTabButton; + if TabPosition = tpTop then + begin + FLeftButton.SetPosition(Width - (FRightButton.Width * 2), FMargin, FRightButton.Height, FRightButton.Height); + FRightButton.SetPosition(Width - FRightButton.Width, FMargin, FRightButton.Height, FRightButton.Height); + end + else + begin + FLeftButton.SetPosition(Width - (FRightButton.Width * 2), Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + FRightButton.SetPosition(Width - FRightButton.Width, Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + end; + FLeftButton.Visible := True; + FRightButton.Visible := True; + end + else + begin + FLeftButton.Visible := False; + FRightButton.Visible := False; + end; + end; + + if TabPosition in [tpLeft, tpRight] then + begin + if MaxButtonHeightSum > (Height-(FMargin*2)) then + begin + if FFirstTabButton = nil then + FFirstTabButton := h + else + h := FFirstTabButton; + if TabPosition = tpLeft then + begin + FLeftButton.SetPosition(MaxButtonWidth - (FRightButton.Width * 2), Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + FRightButton.SetPosition(MaxButtonWidth - FRightButton.Width, Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + end + else + begin + FLeftButton.SetPosition(Width - MaxButtonWidth, Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + FRightButton.SetPosition(Width - MaxButtonWidth + FRightButton.Width, Height - ButtonHeight - FMargin, FRightButton.Height, FRightButton.Height); + end; + FLeftButton.Visible := True; + FRightButton.Visible := True; + end + else + begin + FLeftButton.Visible := False; + FRightButton.Visible := False; + end; + end; + case TabPosition of + tpNone: + begin + while h <> nil do + begin + if h <> ActivePage then + h.Visible:=false + else + h.Visible:=True; + h.SetPosition(FMargin+2, FMargin+2 , Width - (FMargin*2) - 4, Height - ((FMargin+2)*2)); + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; + end; + r2.Left := 0; + r2.Top := 0; + r2.Width := Width; + r2.Height := Height; + Canvas.DrawButtonFace(r2, []); + end; + tpBottom: + begin + lTxtFlags += TextFlagsDflt; + lp := 0; + r2.SetRect(2, Height - ButtonHeight-3, 50, 21); + while h <> nil do begin -(* - if MaxButtonWidthSum > (Width-(FMargin*2)) then + if h <> ActivePage then begin - if FFirstTabButton = nil then - FFirstTabButton := h - else - h := FFirstTabButton; - r.SetRect(FMargin, FMargin, Width-(FMargin*2)-(FRightButton.Width*2)-1, FRightButton.Height); - FLeftButton.SetPosition(Width - FMargin * 2 - FRightButton.Width * 2, FMargin, FRightButton.Height, FRightButton.Height); - FRightButton.SetPosition(Width - FMargin * 2 - FrightButton.Width, FMargin, FRightButton.Height, FRightButton.Height); - FLeftButton.Visible := True; - FRightButton.Visible := True; + toffset := 2; + h.Visible := False; end else begin - r.SetRect(FMargin, FMargin, Width-(FMargin*2), ButtonHeight); - FLeftButton.Visible := False; - FRightButton.Visible := False; + toffset := 4; + h.Visible := True; + h.SetPosition(FMargin+2, FMargin+2 , Width - (FMargin*2) - 4, Height - r2.Height - (FMargin+2)*2); end; - // tabsheet area - left outer line - Canvas.SetColor(clHilite1); - Canvas.DrawLine(FMargin, ButtonHeight, FMargin, Height-(FMargin*2)); - // tabsheet area - left inner line - Canvas.SetColor(clHilite2); - Canvas.DrawLine(FMargin+1, ButtonHeight+1, FMargin+1, Height - (FMargin*2) - 1); - // tabsheet area - outer bottom & right line - Canvas.SetColor(clShadow2); - Canvas.DrawLine(FMargin, Height - (FMargin*2), Width - (FMargin*2), Height - (FMargin*2)); - Canvas.DrawLine(Width - (FMargin*2), Height - (FMargin*2), Width - (FMargin*2), FMargin + ButtonHeight - 3); - // tabsheet area - inner bottom & right line - Canvas.SetColor(clShadow1); - Canvas.DrawLine(FMargin + 1, Height - (FMargin*2) - 1, Width - (FMargin*2) - 1, Height - (FMargin*2) - 1); - Canvas.DrawLine(Width - FMargin - 2, Height - FMargin - 2, Width - FMargin - 2, FMargin + ButtonHeight - 2); - Canvas.SetClipRect(r); - lp := 0; - while h <> nil do - begin - if h <> ActivePage then - begin - toffset := 4; - // tabsheet area - top lines under inactive tabs - Canvas.SetColor(clHilite1); - Canvas.DrawLine(FMargin + lp, FMargin + ButtonHeight - 2, FMargin + lp + ButtonWidth(h.Text), FMargin + ButtonHeight - 2); - Canvas.SetColor(clHilite2); - if TfpgTabSheet(FPages.First) = h then - dx := 1 - else - dx := -1; - Canvas.DrawLine(FMargin + lp+dx, FMargin + ButtonHeight - 1, FMargin + lp + ButtonWidth(h.Text) + 1, FMargin + ButtonHeight - 1); - // vertical divider line between inactive tabs - Canvas.SetColor(clShadow1); - Canvas.DrawLine(lp + FMargin + ButtonWidth(h.Text), FMargin, lp + FMargin + ButtonWidth(h.Text), FMargin + ButtonHeight - 2); - h.Visible := False; - end - else - begin - toffset := 2; - h.Visible := True; - h.SetPosition(FMargin+2, FMargin + ButtonHeight, Width - (FMargin*2) - 4, Height - (FMargin*2) - ButtonHeight - 2); - // tab outer left & top line - Canvas.SetColor(clHilite1); - Canvas.DrawLine(lp + FMargin, FMargin + ButtonHeight - 2, lp + FMargin, FMargin); - Canvas.DrawLine(lp + FMargin, FMargin, lp + FMargin + ButtonWidth(h.Text)-1, FMargin); - // tab inner left & top line - Canvas.SetColor(clHilite2); - Canvas.DrawLine(lp + FMargin + 1, FMargin + ButtonHeight - 1, lp + FMargin + 1, FMargin + 1); - Canvas.DrawLine(lp + FMargin + 1, FMargin + 1, lp + FMargin + ButtonWidth(h.Text) - 2, FMargin + 1); - // tab inner right line - Canvas.SetColor(clShadow1); - Canvas.DrawLine(lp + FMargin + ButtonWidth(h.Text) - 2, FMargin + 1, lp + FMargin + ButtonWidth(h.Text) - 2, FMargin + ButtonHeight); - // tab outer right line - Canvas.SetColor(clShadow2); - Canvas.DrawLine(lp + FMargin + ButtonWidth(h.Text) - 1, FMargin, lp + FMargin + ButtonWidth(h.Text) - 1, FMargin + ButtonHeight-1); - end; - // paint text - Canvas.DrawString(lp + (ButtonWidth(h.Text) div 2) - FFont.TextWidth(GetTabText(h.Text)) div 2, FMargin+toffset, GetTabText(h.Text)); - - lp := lp + ButtonWidth(h.Text); - if h <> TfpgTabSheet(FPages.Last) then - h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) - else - h := nil; - end; { while } - // tabsheet area - top lines on right of tabs - Canvas.SetColor(clHilite1); - Canvas.Drawline(lp + 1, FMargin + ButtonHeight - 2, Width - (FMargin*2), FMargin + ButtonHeight - 2); - Canvas.SetColor(clHilite2); - Canvas.Drawline(lp , FMargin + ButtonHeight - 1, Width - (FMargin*2)-1, FMargin + ButtonHeight - 1); -*) + // paint tab button + r2.Width := ButtonWidth(h.Text); + r3 := DrawTab(r2, h = ActivePage); + // paint text on non-active tabs + if h <> ActivePage then + Canvas.DrawText(lp + (ButtonWidth(h.Text) div 2) - FFont.TextWidth(GetTabText(h.Text)) div 2, + Height-r2.Height-toffset, GetTabText(h.Text), lTxtFlags); + + r2.Left := r2.Left + r2.Width; + lp := lp + ButtonWidth(h.Text); + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; end; + // Draw Page Control body rectangle (client area) + r2.Left := 0; + r2.Top := 0; + r2.Width := Width; + r2.Height := Height - r2.Height; + Canvas.DrawButtonFace(r2, []); + // Draw text of ActivePage, because we didn't before. + DrawTab(r3, false, 2); + Canvas.DrawText(r3.Left+4, r3.Top+5, r3.Width, r3.Height, ActivePage.Text, lTxtFlags); + end; tpTop: + begin + lTxtFlags += TextFlagsDflt; + lp := 0; + r2.SetRect(2, 2, 50, 21); + while h <> nil do begin - if MaxButtonWidthSum > (Width-(FMargin*2)) then + if h <> ActivePage then begin - if FFirstTabButton = nil then - FFirstTabButton := h - else - h := FFirstTabButton; - r.SetRect(FMargin, FMargin, Width-(FMargin*2)-(FRightButton.Width*2)-1, FRightButton.Height); - FLeftButton.SetPosition(Width - FRightButton.Width * 2, FMargin, FRightButton.Height, FRightButton.Height); - FRightButton.SetPosition(Width - FrightButton.Width, FMargin, FRightButton.Height, FRightButton.Height); - FLeftButton.Visible := True; - FRightButton.Visible := True; + toffset := 4; + h.Visible := False; end else begin - r.SetRect(FMargin, FMargin, Width-(FMargin*2), ButtonHeight); - FLeftButton.Visible := False; - FRightButton.Visible := False; + toffset := 2; + h.Visible := True; + h.SetPosition(FMargin+2, FMargin+2 + r2.Height, Width - (FMargin*2) - 4, Height - r2.Height - ((FMargin+2)*2)); end; - - lp := 0; - r2.SetRect(2, 2, 50, 21); - while h <> nil do + // paint tab button + r2.Width := ButtonWidth(h.Text); + r3 := DrawTab(r2, h = ActivePage); + + // paint text on non-active tabs + if h <> ActivePage then + Canvas.DrawText(lp + (ButtonWidth(h.Text) div 2) - FFont.TextWidth(GetTabText(h.Text)) div 2, + FMargin+toffset, GetTabText(h.Text), lTxtFlags); + r2.Left := r2.Left + r2.Width; + lp := lp + ButtonWidth(h.Text); + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; + end; + // Draw Page Control body rectangle (client area) + r2.Left := 0; + r2.Top := r2.Top + r2.Height-2; + r2.Width := Width; + r2.Height := Height - r2.Height; + Canvas.DrawButtonFace(r2, []); + + // Draw text of ActivePage, because we didn't before. + DrawTab(r3, false, 2); + Canvas.DrawText(r3.Left+4, r3.Top+3, r3.Width, r3.Height, ActivePage.Text, lTxtFlags); + end; + + tpRight: + begin + lTxtFlags += [txtVCenter, txtLeft]; + lp := 0; + TabW := MaxButtonWidth; + r2.SetRect(Width - 2 - TabW, 2, TabW, 21); + while h <> nil do + begin + if h <> ActivePage then begin - if h <> ActivePage then - begin - toffset := 4; - h.Visible := False; - end - else - begin - toffset := 2; - h.Visible := True; - h.SetPosition(FMargin+2, FMargin+2 + r2.Height, Width - (FMargin*2) - 4, Height - r2.Height - ((FMargin+2)*2)); - end; - // paint tab button - r2.Width := ButtonWidth(h.Text); - r3 := DrawTab(r2, h = ActivePage); - - // paint text on non-active tabs - if h <> ActivePage then - Canvas.DrawText(lp + (ButtonWidth(h.Text) div 2) - FFont.TextWidth(GetTabText(h.Text)) div 2, FMargin+toffset, GetTabText(h.Text), lTxtFlags); - - r2.Left := r2.Left + r2.Width; - lp := lp + ButtonWidth(h.Text); - if h <> TfpgTabSheet(FPages.Last) then - h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) - else - h := nil; + toffset := 4; + h.Visible := False; + end + else + begin + toffset := 2; + h.Visible := True; + { set tab content page (client area) size } + h.SetPosition(FMargin+2, FMargin+2, Width - ((FMargin+2)*2) - TabW, Height - ((FMargin+2)*2)); end; - // Draw Page Control body rectangle (client area) - r2.Left := 0; - r2.Top := r2.Top + r2.Height-2; - r2.Width := Width; - r2.Height := Height - r2.Height; - Canvas.DrawButtonFace(r2, []); - - // Draw text of ActivePage, because we didn't before. - DrawTab(r3, false, 2); - Canvas.DrawText(r3.Left+4, r3.Top+3, r3.Width, r3.Height, ActivePage.Text, lTxtFlags); + // paint tab button + r3 := DrawTab(r2, h = ActivePage); + + // paint text on non-active tabs + if h <> ActivePage then + Canvas.DrawText(r2.left+toffset, r2.Top, r2.Width, r2.Height, GetTabText(h.Text), lTxtFlags); + r2.Top += r2.Height; + lp := r2.Top; + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; end; - end; - + // Draw Page Control body rectangle (client area) + r2.Left := 0; + r2.Top := 0; + r2.Width := Width - TabW; + r2.Height := Height; + Canvas.DrawButtonFace(r2, []); + + // Draw text of ActivePage, because we didn't before. + DrawTab(r3, false, 2); + Canvas.DrawText(r3.left+toffset, r3.Top, r3.Width, r3.Height, ActivePage.Text, lTxtFlags); + end; + + tpLeft: + begin + lTxtFlags += [txtVCenter, txtLeft]; + lp := 0; + TabW := MaxButtonWidth; + r2.SetRect(2, 2, TabW, 21); + while h <> nil do + begin + if h <> ActivePage then + begin + toffset := 4; + h.Visible := False; + end + else + begin + toffset := 2; + h.Visible := True; + { set tab content page (client area) size } + h.SetPosition(FMargin+2+TabW, FMargin+2, Width - ((FMargin+2)*2) - TabW, Height - ((FMargin+2)*2)); + end; + // paint tab button + r3 := DrawTab(r2, h = ActivePage); + + // paint text on non-active tabs + if h <> ActivePage then + Canvas.DrawText(r2.left+toffset, r2.Top, r2.Width, r2.Height, GetTabText(h.Text), lTxtFlags); + r2.Top += r2.Height; + lp := r2.Top; + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; + end; + // Draw Page Control body rectangle (client area) + r2.Left := TabW; + r2.Top := 0; + r2.Width := Width - TabW; + r2.Height := Height; + Canvas.DrawButtonFace(r2, []); + + // Draw text of ActivePage, because we didn't before. + DrawTab(r3, false, 2); + Canvas.DrawText(r3.left+toffset, r3.Top, r3.Width, r3.Height, ActivePage.Text, lTxtFlags); + end; + end; { case } + Canvas.EndDraw; end; procedure TfpgPageControl.HandlePaint; begin -// inherited HandlePaint; if SortPages then OrderSheets; Canvas.ClearClipRect; @@ -669,15 +966,6 @@ begin Canvas.DrawString(2, 2, Name + ': ' + Classname); end; end; - - if TabPosition = tpBottom then - begin - if Focused then - Canvas.SetColor(clWidgetFrame) - else - Canvas.SetColor(clInactiveWgFrame); - Canvas.DrawRectangle(0, 0, Width, Height); - end; RePaintTitles; end; @@ -693,8 +981,10 @@ var h: TfpgTabSheet; lp: integer; // left position bw: integer; // button width + bh: integer; // button height + p1, p2: integer; // tab boundaries for mouse click to take affect begin -// writeln('>> TfpgPageControl.HandleLMouseUp'); +// debugln('>> TfpgPageControl.HandleLMouseUp'); h := TfpgTabSheet(FPages.First); if h = nil then Exit; //==> @@ -705,58 +995,92 @@ begin case TabPosition of tpTop: - begin -// writeln(' TabPosition = tpTop'); - if (y > FMargin) and (y < ButtonHeight) then - begin - while h <> nil do - begin - bw := ButtonWidth(h.Text); // initialize button width - if (x > lp) and (x < lp + bw) then - begin - if h <> ActivePage then - begin - ActivePage := h; - DoChange(ActivePage); - end; - exit; - end; { if } - lp := lp + bw; - if h <> TfpgTabSheet(FPages.Last) then - h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) - else - h := nil; - end; { while } - end; { if } - end; - + begin + p1 := FMargin; + p2 := ButtonHeight; + end; + tpBottom: - begin -(* - if (y > Height - FMargin - buttonheight) and (y < height - FMargin) then + begin + p1 := Height - FMargin - ButtonHeight; + p2 := Height - FMargin; + end; + + tpRight: + begin + p1 := Width - MaxButtonWidth; + p2 := Width; + end; + + tpLeft: + begin + p1 := FMargin; + p2 := FMargin + MaxButtonWidth; + end; + end; + + if TabPosition in [tpTop, tpBottom] then + begin + if (y > p1) and (y < p2) then + begin + while h <> nil do + begin + bw := ButtonWidth(h.Text); // initialize button width + if (x > lp) and (x < lp + bw) then begin - while h <> nil do - begin - bw := ButtonWidth(h^.TabSheet.Text); // initialize button width - if (x > lp) and (x < lp + bw) then - begin - if h^.TabSheet <> ActiveTabSheet then - begin - ActiveTabSheet := h^.TabSheet; - DoChange(ActiveTabSheet); - end; - exit; - end; - lp := lp + bw; - h := h^.next; - end; { while } + if h <> ActivePage then + ActivePage := h; + exit; end; { if } -*) - end; - end; { case } + lp := lp + bw; + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; + end; { while } + end; { if } + end; + + if TabPosition in [tpLeft, tpRight] then + begin + if (x > p1) and (x < p2) then + begin + while h <> nil do + begin + bh := ButtonHeight; // initialize button height + if (y > lp) and (y < lp + bh) then + begin + if h <> ActivePage then + ActivePage := h; + exit; + end; { if } + lp := lp + bh; + if h <> TfpgTabSheet(FPages.Last) then + h := TfpgTabSheet(FPages[FPages.IndexOf(h)+1]) + else + h := nil; + end; { while } + end; { if } + end; + inherited HandleLMouseUp(x, y, shiftstate); end; +procedure TfpgPageControl.HandleRMouseUp(x, y: integer; shiftstate: TShiftState); +begin + inherited HandleRMouseUp(x, y, shiftstate); +// ShowDefaultPopupMenu(x, y, ShiftState); + if to_PMenuClose in FTabOptions then + begin + if not Assigned(FPopupMenu) then + begin + FPopupMenu := TfpgPopupMenu.Create(self); + FPopupMenu.AddMenuItem('Close Tab', '', @pmCloseTab); + end; + FPopupMenu.ShowAt(self, x, y); + end; +end; + procedure TfpgPageControl.HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); var @@ -765,14 +1089,13 @@ begin // writeln(Classname, '.Keypress'); consumed := True; i := ActivePageIndex; - + if ssAlt in shiftstate then case keycode of keyLeft: begin if ActivePage <> TfpgTabSheet(FPages.First) then begin ActivePage := TfpgTabSheet(FPages[i-1]); - DoChange(ActivePage); end; end; @@ -781,7 +1104,6 @@ begin if ActivePage <> TfpgTabSheet(FPages.Last) then begin ActivePage := TfpgTabSheet(FPages[i+1]); - DoChange(ActivePage); end; end; @@ -799,12 +1121,14 @@ begin FWidth := 150; FHeight := 100; FIsContainer := True; + FTabOptions := []; FTextColor := Parent.TextColor; FBackgroundColor := Parent.BackgroundColor; FFocusable := True; FOnChange := nil; FFixedTabWidth := 0; + FFixedTabHeight := 21; FFirstTabButton := nil; FStyle := tsTabs; FTabPosition := tpTop; @@ -825,20 +1149,13 @@ begin end; destructor TfpgPageControl.Destroy; -var - ts: TfpgTabSheet; +var i: integer; begin FOnChange := nil; - if FPages.Count > 0 then - FActivePage := TfpgTabSheet(FPages[0]); - ActiveWidget := nil; - while FPages.Count > 0 do - begin - ts := TfpgTabSheet(FPages.Last); - FPages.Remove(ts); - ts.Free; - end; + for i:=0 to FPages.Count-1 do + TfpgTabSheet(FPages[i]).PageControl:=nil; FPages.Free; + ActiveWidget := nil; FFirstTabButton := nil; inherited Destroy; end; |