summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraeme Geldenhuys <graemeg@gmail.com>2013-04-29 14:11:53 +0100
committerGraeme Geldenhuys <graemeg@gmail.com>2013-04-29 14:11:53 +0100
commit97ba8bdef93c9f23c7f7890b5cd2f89a94c0905c (patch)
treec9fd96432a6e763a0f0fd3c0fde565d00efaa24b /src
parent5d1926a9f9ea9b0d46145fab6e81e82f9ba459e2 (diff)
parente6ec10df9b5a02dd61063627e8bb353d7ccd5f75 (diff)
downloadfpGUI-97ba8bdef93c9f23c7f7890b5cd2f89a94c0905c.tar.xz
Merge remote-tracking branch 'demerson3/grids' into develop
This feature branch contains grid scrollbar improvements, and a new virtual method for end-user optimisation when using grids.
Diffstat (limited to 'src')
-rw-r--r--src/gui/fpg_basegrid.pas259
1 files changed, 210 insertions, 49 deletions
diff --git a/src/gui/fpg_basegrid.pas b/src/gui/fpg_basegrid.pas
index 51b50408..3b0e445f 100644
--- a/src/gui/fpg_basegrid.pas
+++ b/src/gui/fpg_basegrid.pas
@@ -50,6 +50,9 @@ type
// Column 2 is special just for testing purposes. Descendant classes will
// override that special behavior anyway.
+
+ { TfpgBaseGrid }
+
TfpgBaseGrid = class(TfpgWidget)
private
FColResizing: boolean;
@@ -137,6 +140,7 @@ type
procedure HandleLMouseDown(x, y: integer; shiftstate: TShiftState); override;
procedure HandleRMouseUp(x, y: integer; shiftstate: TShiftState); override;
procedure FollowFocus; virtual;
+ procedure PrepareCells (firstrow, lastrow, firstcol, lastcol : integer); virtual;
property AlternateBGColor: TfpgColor read FAlternativeBGColor write SetAlternativeBGColor default clHilite1;
property BorderStyle: TfpgEditBorderStyle read FBorderStyle write SetBorderStyle default ebsDefault;
property DefaultColWidth: integer read FDefaultColWidth write SetDefaultColWidth default 64;
@@ -585,39 +589,118 @@ var
VHeight: integer;
vw: integer;
cw: integer;
+ vl: integer;
i: integer;
x: integer;
+ Hfits, showH : boolean;
+ Vfits, showV : boolean;
+
+ procedure hideScrollbar (sb : TfpgScrollBar);
+ begin
+ with sb do
+ if Visible then
+ begin
+ Visible := False;
+ UpdateWindowPosition;
+ end;
+ end;
+
+ procedure getVisWidth;
+ begin
+ if showV then
+ vw := HWidth - (FVScrollBar.Width-1)
+ else
+ vw := HWidth;
+ Hfits := vw >= cw;
+ end;
+
+ procedure getVisLines;
+ var
+ hh : integer; // header height
+ begin
+ hh := 0;
+ if ShowHeader then inc (hh, FHeaderHeight+1);
+ if showH then inc (hh, FHScrollBar.Height);
+ vl := (VHeight - hh) div FDefaultRowHeight;
+ Vfits := vl >= RowCount;
+ end;
+
begin
+ // if we don't want any scrollbars, hide them and exit
+ if FScrollBarStyle = ssNone then
+ begin
+ hideScrollbar (FHScrollBar);
+ hideScrollbar (FVScrollBar);
+ exit;
+ end;
+
+ // preliminary width/height calculations
VHeight := Height - 4;
HWidth := Width - 4;
-
- vw := VisibleWidth;
cw := 0;
for i := 0 to ColumnCount-1 do
cw := cw + ColumnWidth[i];
-
- // This needs improving while resizing
- if cw > vw then
- FHScrollBar.Visible := not (FScrollBarStyle in [ssNone, ssVertical])
- else
- begin
- FHScrollBar.Visible := False;
- FFirstCol := 0;
- FXOffset := 0;
- end;
+ showV := False;
+ showH := False;
+ getVisWidth;
+ getVisLines;
- // This needs improving while resizing
- if (RowCount > VisibleLines) then
- FVScrollBar.Visible := not (FScrollBarStyle in [ssNone, ssHorizontal])
- else
- begin
- FVScrollBar.Visible := False;
- FFirstRow := 0;
+ // determine whether to show scrollbars for different configurations
+ case FScrollBarStyle of
+ ssHorizontal:
+ begin
+ hideScrollbar (FVScrollBar);
+ if not Hfits then
+ begin
+ showH := true;
+ getVisLines;
+ end;
+ end;
+ ssVertical:
+ begin
+ hideScrollbar (FHScrollBar);
+ if not Vfits then
+ begin
+ showV := true;
+ getVisWidth;
+ end;
+ end;
+ ssAutoBoth:
+ if not Vfits then
+ begin
+ showV := true;
+ getVisWidth;
+ if not Hfits then
+ begin
+ showH := true;
+ getVisLines;
+ getVisWidth;
+ end;
+ end
+ else if not Hfits then
+ begin
+ showH := true;
+ getVisLines;
+ if not Vfits then
+ begin
+ showV := true;
+ getVisWidth;
+ getVisLines;
+ end;
+ end;
end;
- if FVScrollBar.Visible then
- begin
+ // set the scrollbar width/height space
+ if showV then
Dec(HWidth, FVScrollBar.Width);
+ if showH then
+ Dec(VHeight, FHScrollBar.Height);
+
+ // show or hide the scrollbars
+
+ if showV then
+ begin
+ FVScrollBar.Visible := true;
FVScrollBar.Min := 0;
if RowCount > 0 then
FVScrollBar.SliderSize := VisibleLines / RowCount
@@ -626,35 +709,52 @@ begin
FVScrollBar.Max := RowCount-VisibleLines;
FVScrollBar.Position := FFirstRow;
FVScrollBar.RepaintSlider;
+ FVScrollBar.Top := 2;
+ FVScrollBar.Left := Width - FVScrollBar.Width - 2;
+ FVScrollBar.Height := VHeight;
+ end
+ else
+ begin
+ FVScrollBar.Visible := false;
+ if Vfits then
+ FFirstRow := 0;
+ // if vertical doesn't fit and no scrollbar, do not change firstrow
end;
-
- if FHScrollBar.Visible then
+
+ if showH then
begin
- Dec(VHeight, FHScrollBar.Height);
+ FHScrollBar.Visible := true;
FHScrollBar.Min := 0;
if go_SmoothScroll in FOptions then
begin
FHScrollBar.Max := cw - vw;
FHScrollBar.Position := FXOffset;
- FHScrollBar.SliderSize := Width / TotalColumnWidth;
+ FHScrollBar.SliderSize := HWidth / TotalColumnWidth;
+ FHScrollBar.PageSize := 5;
end
else
begin
FHScrollBar.Max := ColumnCount-1;
FHScrollBar.Position := FFirstCol;
FHScrollBar.SliderSize := 1 / ColumnCount;
+ FHScrollBar.PageSize := 1;
end;
FHScrollBar.RepaintSlider;
+ FHScrollBar.Top := Height -FHScrollBar.Height - 2;
+ FHScrollBar.Left := 2;
+ FHScrollBar.Width := HWidth;
+ end
+ else
+ begin
+ FHScrollBar.Visible := false;
+ if Hfits then
+ begin
+ FFirstCol := 0;
+ FXOffset := 0;
+ end;
+ // if horizontal doesn't fit and no scrollbar, do not change firstcol/xoffset
end;
- FHScrollBar.Top := Height -FHScrollBar.Height - 2;
- FHScrollBar.Left := 2;
- FHScrollBar.Width := HWidth;
-
- FVScrollBar.Top := 2;
- FVScrollBar.Left := Width - FVScrollBar.Width - 2;
- FVScrollBar.Height := VHeight;
-
FVScrollBar.UpdateWindowPosition;
FHScrollBar.UpdateWindowPosition;
end;
@@ -673,7 +773,9 @@ var
clipr: TfpgRect; // clip rectangle
drawstate: TfpgGridDrawState;
cLeft: integer;
- c: integer;
+ rTop: integer;
+ firstcol, lastcol, firstrow, lastrow : integer;
+ cWidths: array of integer;
begin
Canvas.ClearClipRect;
@@ -704,32 +806,87 @@ begin
r := clipr;
cLeft := FMargin; // column starting point
+ rTop := FMargin; // row starting point
+
if go_SmoothScroll in FOptions then
begin
if FHScrollBar.Visible then
Dec(cLeft, FHScrollBar.Position);
- c := 0;
+ firstcol := 0;
end
else
begin
- c := FFirstCol;
+ firstcol := FFirstCol;
end;
+ // calculate column widths, and first/last columns
+ if (ColumnCount <= 0) then
+ begin
+ firstcol := -1;
+ lastcol := -2;
+ end
+ else
+ begin
+ setlength (cWidths, ColumnCount);
+ r.Left := cLeft;
+ for col := firstcol to ColumnCount-1 do
+ begin
+ cWidths[col] := ColumnWidth[col];
+ r.Width := cWidths[col];
+ if (go_SmoothScroll in FOptions) and (r.Left <= clipr.Left) then
+ begin
+ firstcol := col;
+ if col>0 then inc (cLeft, cWidths[col-1]);
+ end;
+ lastcol := col;
+ if r.Right >= clipr.Right then
+ break;
+ inc (r.Left, r.Width);
+ end;
+ // first/last rows...
+ if (RowCount <= 0) then
+ begin
+ firstrow := -1;
+ lastrow := -2;
+ end
+ else
+ begin
+ if ShowHeader then
+ inc (r.Top, FHeaderHeight);
+ if r.Top > clipr.Bottom then
+ begin
+ firstrow := -1;
+ lastrow := -2;
+ end
+ else
+ begin
+ firstrow := FFirstRow;
+ lastrow := firstrow + (clipr.Bottom - r.Top) div DefaultRowHeight;
+ if lastrow >= RowCount then
+ lastrow := RowCount-1;
+ end;
+ end;
+ end;
+
+ PrepareCells (firstrow, lastrow, firstcol, lastcol);
+
+ r.Left := cLeft;
+ r.Top := rTop;
+
if (ColumnCount > 0) and ShowHeader then
begin
// Drawing horizontal headers
- r.Left := cLeft;
r.Height := FHeaderHeight;
Canvas.SetFont(FHeaderFont);
- for col := c to ColumnCount-1 do
+ for col := firstcol to lastcol do
begin
- r.Width := ColumnWidth[col];
+ r.Width := cWidths[col];
Canvas.SetClipRect(clipr);
Canvas.AddClipRect(r);
DrawHeader(col, r, 0);
inc(r.Left, r.Width);
- if r.Left >= clipr.Right then
- Break; // small optimization. Don't draw what we can't see
+ //if r.Left >= clipr.Right then
+ // Break; // optimization made obsolete by lastcol
end;
inc(r.Top, r.Height);
end;
@@ -740,13 +897,13 @@ begin
r.Height := DefaultRowHeight;
Canvas.SetFont(FFont);
- for row := FFirstRow to RowCount-1 do
+ for row := firstrow to lastrow do
begin
r.Left := cLeft;
- for col := c to ColumnCount-1 do
+ for col := firstcol to lastcol do
begin
drawstate := [];
- r.Width := ColumnWidth[col];
+ r.Width := cWidths[col];
Canvas.SetClipRect(clipr);
if (row = FFocusRow) and (RowSelect or (col = FFocusCol)) and not (go_HideFocusRect in FOptions) then
@@ -774,7 +931,6 @@ begin
Include(drawstate, gdFocused);
if (row = FFocusRow) and (col = FFocusCol) then
Include(drawstate, gdSelected);
-
if DoDrawCellEvent(row, col, r, drawstate) then
DrawCell(row, col, r, drawstate);
@@ -783,13 +939,13 @@ begin
DrawGrid(row, col, r, 0);
inc(r.Left, r.Width);
- if r.Left >= clipr.Right then
- Break; // small optimization. Don't draw what we can't see
+ //if r.Left >= clipr.Right then
+ // Break; // optimization made obsolete by lastcol
end;
// Inc(r.Top, FDefaultRowHeight+1);
inc(r.Top, r.Height);
- if r.Top >= clipr.Bottom then
- break;
+ //if r.Top >= clipr.Bottom then
+ // break; // optimization made obsolete by lastrow
end;
end; // item drawing
@@ -1283,6 +1439,11 @@ begin
UpdateScrollBars;
end;
+procedure TfpgBaseGrid.PrepareCells(firstrow, lastrow, firstcol, lastcol: integer);
+begin
+ // for descendents
+end;
+
constructor TfpgBaseGrid.Create(AOwner: TComponent);
begin
Updating;