From 9757d10df309bd50743bd98845ab48f9400ffbfd Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 28 May 2014 09:04:42 +0000 Subject: [PATCH] fpspreadsheet: Fix text alignment issues of rotated text in TsWorksheetGrid. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3111 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/fpsgrid/mainform.lfm | 44 +++++++++--------- .../examples/fpsgrid/mainform.lrs | 38 ++++++++-------- .../fpspreadsheet/fpspreadsheetgrid.pas | 45 ++++++++++++++----- 3 files changed, 75 insertions(+), 52 deletions(-) diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm index 863e696e2..955ab3fb5 100644 --- a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm +++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm @@ -4,7 +4,7 @@ object Form1: TForm1 Top = 193 Width = 884 Caption = 'fpsGrid' - ClientHeight = 629 + ClientHeight = 624 ClientWidth = 884 Menu = MainMenu OnActivate = FormActivate @@ -14,7 +14,7 @@ object Form1: TForm1 object Panel1: TPanel Left = 0 Height = 85 - Top = 544 + Top = 539 Width = 884 Align = alBottom BevelOuter = bvNone @@ -23,9 +23,9 @@ object Form1: TForm1 TabOrder = 0 object CbShowHeaders: TCheckBox Left = 8 - Height = 19 + Height = 24 Top = 8 - Width = 93 + Width = 116 Caption = 'Show headers' Checked = True OnClick = CbShowHeadersClick @@ -34,9 +34,9 @@ object Form1: TForm1 end object CbShowGridLines: TCheckBox Left = 8 - Height = 19 + Height = 24 Top = 32 - Width = 100 + Width = 125 Caption = 'Show grid lines' Checked = True OnClick = CbShowGridLinesClick @@ -45,7 +45,7 @@ object Form1: TForm1 end object EdFrozenCols: TSpinEdit Left = 238 - Height = 23 + Height = 28 Top = 8 Width = 52 OnChange = EdFrozenColsChange @@ -53,7 +53,7 @@ object Form1: TForm1 end object EdFrozenRows: TSpinEdit Left = 238 - Height = 23 + Height = 28 Top = 39 Width = 52 OnChange = EdFrozenRowsChange @@ -61,27 +61,27 @@ object Form1: TForm1 end object Label1: TLabel Left = 152 - Height = 15 + Height = 20 Top = 13 - Width = 62 + Width = 77 Caption = 'Frozen cols:' FocusControl = EdFrozenCols ParentColor = False end object Label2: TLabel Left = 153 - Height = 15 + Height = 20 Top = 40 - Width = 66 + Width = 82 Caption = 'Frozen rows:' FocusControl = EdFrozenRows ParentColor = False end object CbReadFormulas: TCheckBox Left = 8 - Height = 19 + Height = 24 Top = 56 - Width = 96 + Width = 120 Caption = 'Read formulas' OnChange = CbReadFormulasChange TabOrder = 4 @@ -89,7 +89,7 @@ object Form1: TForm1 end object PageControl1: TPageControl Left = 0 - Height = 465 + Height = 460 Top = 79 Width = 884 ActivePage = TabSheet1 @@ -99,11 +99,11 @@ object Form1: TForm1 OnChange = PageControl1Change object TabSheet1: TTabSheet Caption = 'Sheet1' - ClientHeight = 437 + ClientHeight = 427 ClientWidth = 876 object WorksheetGrid: TsWorksheetGrid Left = 0 - Height = 437 + Height = 427 Top = 0 Width = 876 FrozenCols = 0 @@ -118,7 +118,7 @@ object Form1: TForm1 TitleStyle = tsNative OnSelection = WorksheetGridSelection ColWidths = ( - 42 + 56 64 ) end @@ -196,19 +196,19 @@ object Form1: TForm1 end object FontComboBox: TComboBox Left = 52 - Height = 23 + Height = 28 Top = 2 Width = 127 - ItemHeight = 15 + ItemHeight = 20 OnSelect = FontComboBoxSelect TabOrder = 0 end object FontSizeComboBox: TComboBox Left = 179 - Height = 23 + Height = 28 Top = 2 Width = 48 - ItemHeight = 15 + ItemHeight = 20 Items.Strings = ( '8' '9' diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs index dfc59234c..37d0f5608 100644 --- a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs +++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs @@ -2,39 +2,39 @@ LazarusResources.Add('TForm1','FORMDATA',[ 'TPF0'#6'TForm1'#5'Form1'#4'Left'#3'g'#1#6'Height'#3#137#2#3'Top'#3#193#0#5'W' - +'idth'#3't'#3#7'Caption'#6#7'fpsGrid'#12'ClientHeight'#3'u'#2#11'ClientWidth' + +'idth'#3't'#3#7'Caption'#6#7'fpsGrid'#12'ClientHeight'#3'p'#2#11'ClientWidth' +#3't'#3#4'Menu'#7#8'MainMenu'#10'OnActivate'#7#12'FormActivate'#8'OnCreate'#7 +#10'FormCreate'#8'ShowHint'#9#10'LCLVersion'#6#3'1.3'#0#6'TPanel'#6'Panel1'#4 - +'Left'#2#0#6'Height'#2'U'#3'Top'#3' '#2#5'Width'#3't'#3#5'Align'#7#8'alBotto' + +'Left'#2#0#6'Height'#2'U'#3'Top'#3#27#2#5'Width'#3't'#3#5'Align'#7#8'alBotto' +'m'#10'BevelOuter'#7#6'bvNone'#12'ClientHeight'#2'U'#11'ClientWidth'#3't'#3#8 - +'TabOrder'#2#0#0#9'TCheckBox'#13'CbShowHeaders'#4'Left'#2#8#6'Height'#2#19#3 - +'Top'#2#8#5'Width'#2']'#7'Caption'#6#12'Show headers'#7'Checked'#9#7'OnClick' + +'TabOrder'#2#0#0#9'TCheckBox'#13'CbShowHeaders'#4'Left'#2#8#6'Height'#2#24#3 + +'Top'#2#8#5'Width'#2't'#7'Caption'#6#12'Show headers'#7'Checked'#9#7'OnClick' +#7#18'CbShowHeadersClick'#5'State'#7#9'cbChecked'#8'TabOrder'#2#0#0#0#9'TChe' - +'ckBox'#15'CbShowGridLines'#4'Left'#2#8#6'Height'#2#19#3'Top'#2' '#5'Width'#2 - +'d'#7'Caption'#6#15'Show grid lines'#7'Checked'#9#7'OnClick'#7#20'CbShowGrid' + +'ckBox'#15'CbShowGridLines'#4'Left'#2#8#6'Height'#2#24#3'Top'#2' '#5'Width'#2 + +'}'#7'Caption'#6#15'Show grid lines'#7'Checked'#9#7'OnClick'#7#20'CbShowGrid' +'LinesClick'#5'State'#7#9'cbChecked'#8'TabOrder'#2#1#0#0#9'TSpinEdit'#12'EdF' - +'rozenCols'#4'Left'#3#238#0#6'Height'#2#23#3'Top'#2#8#5'Width'#2'4'#8'OnChan' + +'rozenCols'#4'Left'#3#238#0#6'Height'#2#28#3'Top'#2#8#5'Width'#2'4'#8'OnChan' +'ge'#7#18'EdFrozenColsChange'#8'TabOrder'#2#2#0#0#9'TSpinEdit'#12'EdFrozenRo' - +'ws'#4'Left'#3#238#0#6'Height'#2#23#3'Top'#2''''#5'Width'#2'4'#8'OnChange'#7 + +'ws'#4'Left'#3#238#0#6'Height'#2#28#3'Top'#2''''#5'Width'#2'4'#8'OnChange'#7 +#18'EdFrozenRowsChange'#8'TabOrder'#2#3#0#0#6'TLabel'#6'Label1'#4'Left'#3#152 - +#0#6'Height'#2#15#3'Top'#2#13#5'Width'#2'>'#7'Caption'#6#12'Frozen cols:'#12 + +#0#6'Height'#2#20#3'Top'#2#13#5'Width'#2'M'#7'Caption'#6#12'Frozen cols:'#12 +'FocusControl'#7#12'EdFrozenCols'#11'ParentColor'#8#0#0#6'TLabel'#6'Label2'#4 - +'Left'#3#153#0#6'Height'#2#15#3'Top'#2'('#5'Width'#2'B'#7'Caption'#6#12'Froz' + +'Left'#3#153#0#6'Height'#2#20#3'Top'#2'('#5'Width'#2'R'#7'Caption'#6#12'Froz' +'en rows:'#12'FocusControl'#7#12'EdFrozenRows'#11'ParentColor'#8#0#0#9'TChec' - +'kBox'#14'CbReadFormulas'#4'Left'#2#8#6'Height'#2#19#3'Top'#2'8'#5'Width'#2 - +'`'#7'Caption'#6#13'Read formulas'#8'OnChange'#7#20'CbReadFormulasChange'#8 + +'kBox'#14'CbReadFormulas'#4'Left'#2#8#6'Height'#2#24#3'Top'#2'8'#5'Width'#2 + +'x'#7'Caption'#6#13'Read formulas'#8'OnChange'#7#20'CbReadFormulasChange'#8 +'TabOrder'#2#4#0#0#0#12'TPageControl'#12'PageControl1'#4'Left'#2#0#6'Height' - +#3#209#1#3'Top'#2'O'#5'Width'#3't'#3#10'ActivePage'#7#9'TabSheet1'#5'Align'#7 + +#3#204#1#3'Top'#2'O'#5'Width'#3't'#3#10'ActivePage'#7#9'TabSheet1'#5'Align'#7 +#8'alClient'#8'TabIndex'#2#0#8'TabOrder'#2#1#8'OnChange'#7#18'PageControl1Ch' +'ange'#0#9'TTabSheet'#9'TabSheet1'#7'Caption'#6#6'Sheet1'#12'ClientHeight'#3 - +#181#1#11'ClientWidth'#3'l'#3#0#15'TsWorksheetGrid'#13'WorksheetGrid'#4'Left' - +#2#0#6'Height'#3#181#1#3'Top'#2#0#5'Width'#3'l'#3#10'FrozenCols'#2#0#10'Froz' + +#171#1#11'ClientWidth'#3'l'#3#0#15'TsWorksheetGrid'#13'WorksheetGrid'#4'Left' + +#2#0#6'Height'#3#171#1#3'Top'#2#0#5'Width'#3'l'#3#10'FrozenCols'#2#0#10'Froz' +'enRows'#2#0#5'Align'#7#8'alClient'#8'ColCount'#2#2#14'ExtendedSelect'#8#16 +'MouseWheelOption'#7#6'mwGrid'#7'Options'#11#15'goFixedVertLine'#15'goFixedH' +'orzLine'#10'goVertLine'#10'goHorzLine'#13'goRangeSelect'#11'goRowSizing'#11 +'goColSizing'#15'goThumbTracking'#14'goSmoothScroll'#16'goFixedColSizing'#0#8 +'RowCount'#2#2#8'TabOrder'#2#0#10'TitleStyle'#7#8'tsNative'#11'OnSelection'#7 - +#22'WorksheetGridSelection'#9'ColWidths'#1#2'*'#2'@'#0#0#0#0#0#8'TToolBar'#8 + +#22'WorksheetGridSelection'#9'ColWidths'#1#2'8'#2'@'#0#0#0#0#0#8'TToolBar'#8 +'ToolBar1'#4'Left'#2#0#6'Height'#2#26#3'Top'#2#0#5'Width'#3't'#3#12'ButtonHe' +'ight'#2#24#7'Caption'#6#8'ToolBar1'#11'EdgeBorders'#11#0#6'Images'#7#9'Imag' +'eList'#8'TabOrder'#2#2#0#11'TToolButton'#11'ToolButton1'#4'Left'#2#1#3'Top' @@ -51,10 +51,10 @@ LazarusResources.Add('TForm1','FORMDATA',[ +#1#3'Top'#2#2#6'Action'#7#11'AcLeftAlign'#4'Wrap'#9#0#0#11'TToolButton'#12'T' +'oolButton12'#4'Left'#3'['#1#3'Top'#2#2#6'Action'#7#16'AcHorCenterAlign'#0#0 +#11'TToolButton'#12'ToolButton13'#4'Left'#3'r'#1#3'Top'#2#2#6'Action'#7#12'A' - +'cRightAlign'#0#0#9'TComboBox'#12'FontComboBox'#4'Left'#2'4'#6'Height'#2#23#3 - +'Top'#2#2#5'Width'#2#127#10'ItemHeight'#2#15#8'OnSelect'#7#18'FontComboBoxSe' + +'cRightAlign'#0#0#9'TComboBox'#12'FontComboBox'#4'Left'#2'4'#6'Height'#2#28#3 + +'Top'#2#2#5'Width'#2#127#10'ItemHeight'#2#20#8'OnSelect'#7#18'FontComboBoxSe' +'lect'#8'TabOrder'#2#0#0#0#9'TComboBox'#16'FontSizeComboBox'#4'Left'#3#179#0 - +#6'Height'#2#23#3'Top'#2#2#5'Width'#2'0'#10'ItemHeight'#2#15#13'Items.String' + +#6'Height'#2#28#3'Top'#2#2#5'Width'#2'0'#10'ItemHeight'#2#20#13'Items.String' +'s'#1#6#1'8'#6#1'9'#6#2'10'#6#2'11'#6#2'12'#6#2'14'#6#2'16'#6#2'18'#6#2'20'#6 +#2'24'#0#8'OnSelect'#7#22'FontSizeComboBoxSelect'#8'TabOrder'#2#1#0#0#11'TTo' +'olButton'#11'ToolButton7'#4'Left'#3#227#0#3'Top'#2#2#6'Action'#7#10'AcFontB' diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas index 820f38240..7b8cb38b7 100644 --- a/components/fpspreadsheet/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/fpspreadsheetgrid.pas @@ -916,6 +916,7 @@ begin wrapped := (uffWordWrap in lCell^.UsedFormattingFields) or (lCell^.TextRotation = rtStacked); txtRot := lCell^.TextRotation; vertAlign := lCell^.VertAlignment; + if vertAlign = vaDefault then vertAlign := vaBottom; if lCell^.HorAlignment <> haDefault then horAlign := lCell^.HorAlignment else begin @@ -953,10 +954,26 @@ begin txt := GetCellText(ACol, ARow); if txt = '' then exit; - case horAlign of - haLeft : justif := 0; - haCenter : justif := 1; - haRight : justif := 2; + case txtRot of + trHorizontal: + case horAlign of + haLeft : justif := 0; + haCenter : justif := 1; + haRight : justif := 2; + end; + rtStacked, + rt90DegreeClockwiseRotation: + case vertAlign of + vaTop : justif := 0; + vaCenter: justif := 1; + vaBottom: justif := 2; + end; + rt90DegreeCounterClockwiseRotation: + case vertAlign of + vaTop : justif := 2; + vaCenter: justif := 1; + vaBottom: justif := 0; + end; end; InternalDrawTextInCell(txt, txt, ARect, justif, horAlign, vertAlign, txtRot, wrapped, false); @@ -1609,8 +1626,10 @@ begin if lCell^.TextRotation = rtStacked then begin s := Result; Result := ''; - for i:=1 to Length(s) do - Result := Result + s[i] + LineEnding; + for i:=1 to Length(s) do begin + Result := Result + s[i]; + if i < Length(s) then Result := Result + LineEnding; + end; end; end; end; @@ -1865,7 +1884,7 @@ begin end; -{ Internal generl text drawing method. +{ Internal general text drawing method. - AText: text to be drawn - AMeasureText: text used for checking if the text fits into the text rectangle. If too large and ReplaceTooLong = true, a series of # is drawn. @@ -1876,9 +1895,12 @@ end; - ACellHorAlign: Is the HorAlignment property stored in the cell - ACellVertAlign: Is the VertAlignment property stored in the cell - ATextRot: determines the rotation angle of the text. - - ATextWrap: determines if the text can wrap over multiple lines - - ReplaceTooLang: if true too-long texts are replaced by a series of # filling - the cell. } + - ATextWrap: determines if the text can wrap into multiple lines + - ReplaceTooLang: if true too-long texts are replaced by a series of # chars + filling the cell. + The reason to separate AJustification from ACellHorAlign and ACelVertAlign is + the output of nfAccounting formatted numbers where the numbers are always + right-aligned, and the currency symbol is left-aligned. } procedure TsCustomWorksheetGrid.InternalDrawTextInCell(AText, AMeasureText: String; ARect: TRect; AJustification: Byte; ACellHorAlign: TsHorAlignment; ACellVertAlign: TsVertAlignment; ATextRot: TsTextRotation; @@ -1991,6 +2013,7 @@ begin h := hline; h0 := 0; end; + // w and h are seen along the text direction, not x/y! if w > ARect.Bottom - ARect.Top then begin if ReplaceTooLong then begin @@ -2022,7 +2045,7 @@ begin case AJustification of 0: P.Y := ARect.Top; // corresponds to "top" 1: P.Y := Max(ARect.Top, (Arect.Top + ARect.Bottom - w) div 2); // "center" - 2: P.Y := Max(ARect.Top, ARect.Bottom -w); // "bottom" + 2: P.Y := Max(ARect.Top, ARect.Bottom - w); // "bottom" end; { case vertAlign of vaTop : P.Y := ARect.Top;