Difference between revisions of "BidiMode"

From Lazarus wiki
Jump to navigationJump to search
Line 107: Line 107:
 
''done here for Win32''
 
''done here for Win32''
  
  TForm {done}  
+
TForm {done}  
  TLabel {done} Alignment reverse when bdRightToLeft
+
TLabel {done} Alignment reverse when bdRightToLeft
  TButton {done}
+
TButton {done}
  TEdit {done}
+
TEdit {done}
  TListBox {done}
+
TListBox {done}
  TComboBox {done}
+
TComboBox {done}
  TCheckBox {done}
+
TCheckBox {done}
  TStaticText {done}
+
TStaticText {done}
  TGroupBox {done}
+
TGroupBox {done}
  TRadioButton {done} (in Win32 need RecreateWnd in SetBidiMode)
+
TRadioButton {done} (in Win32 need RecreateWnd in SetBidiMode)
  TMenu/TMenuItem {done} [http://support.microsoft.com/kb/253308 there is a bug in windows]   
+
TMenu/TMenuItem {done} [http://support.microsoft.com/kb/253308 there is a bug in windows]   
    With Menus in Lazarus Win32 the developers force to make it OWNERDRAW, We want to modify DrawMenuItem functions {done}.
+
    With Menus in Lazarus Win32 the developers force to make it OWNERDRAW, We want to modify DrawMenuItem functions {done}.
  TScrollbar {not supported by Win32} Delphi emulate it by change the position with virtual position.
+
TScrollbar {not supported by Win32} Delphi emulate it by change the position with virtual position.
  
  
 
'''In progress'''   
 
'''In progress'''   
 
   TApplication {done} Changing the BidiMode will fire ParentBidiModeChanged and FlipChildren to all TComponent and TControls owned by Application, and also FlipChildrens will reverse the Anchors as like Align property.
 
   TApplication {done} Changing the BidiMode will fire ParentBidiModeChanged and FlipChildren to all TComponent and TControls owned by Application, and also FlipChildrens will reverse the Anchors as like Align property.
  Application.AutoFlipControls:Boolean; {not yet}
+
Application.AutoFlipControls:Boolean; {not yet}
  When Application.AutoFlipControls is True and change the Application.BidiMode value Application object send to all form to FlipControls.
+
When Application.AutoFlipControls is True and change the Application.BidiMode value Application object send to all form to FlipControls.
  it is useful when changing the language from "Left To Right" language like as English to Arabic and vise versa.
+
it is useful when changing the language from "Left To Right" language like as English to Arabic and vise versa.
 +
TBitBtn {} Layout glyph will reversed between Right and Left
 +
TSpeedBtn {} Layout glyph will reversed
  
  TBitBtn {} Layout glyph will reversed between Right and Left
+
TRadioGroup {It use ChildSizing more complex code for me and sensitive area}
  TSpeedBtn {} Layout glyph will reversed
+
TCheckGroup  
 
+
TGrid {}
  TRadioGroup {It use ChildSizing more complex code for me and sensitive area}
 
  TCheckGroup  
 
  TGrid {}
 
 
    
 
    
 
Delphi use CanvasOrientation for mirror the control and maked RightToLeft, i hate use this because it flip the shadow and images (like as the Check) it is make the control ugly.
 
Delphi use CanvasOrientation for mirror the control and maked RightToLeft, i hate use this because it flip the shadow and images (like as the Check) it is make the control ugly.

Revision as of 15:40, 1 June 2009

Some languages (Arabic, Hebrew, Farsi ...) write the characters from the right to the left, and adequate support for this must be implemented on Lazarus.

BidiMode

 bdLeftToRight
 bdRightToLeft
 bdRightToLeftNoAlign
 bdRightToLeftReadingOnly
bdLeftToRight

Default of BidiMode, mean read and order is normal "Left To Right"

bdRightToLeft

Makes a control Right To Left reading text and right alignment depend a kind of the control,

In Delphi if there is Alignment property effect by reverse taLeft to taRight and vise versa, but in Lazarus we will reverse the alignment with FlipControls function, that make more consistency with Anchors and Align properties. Also bdRightToLeft take a Scrollbar at the Left and if there is a Cells or Menus must ordered from the Right.

 For Example
 in bdLeftToRight:
   Menu1, Menu2, Menu2
 in bdRightToLeft: 
   Menu3, Menu2, Menu1

That mean not just a Right Alignment it is Right To Left Order. bdRightToLeft must effect the text reading as depend on the OS if it is supported, the sentence words take as like Cells

 in bdLeftToRight:
   Word1 Word2 Word2
 in bdRightToLeft: 
   Word3 Word2 Word1

We are reading the Word1 first then Word2, We read from the Right to Left, but Draw Text is more complicated than normal Cells, in fact the function that Draw the text care about English/Latin words and draw it Left To Right, so if we mixed both languages in the same sentence the draw function drawing continual English words by Left To Right order to make it more readable, but a symbols like as ? or ! considered as Right To Left characters.

For testing purpose i used English word with a symbol to test Right To Left text reading

Like as Word?

For special states or in fact for more compatibly with Delphi there is another values

bdRightToLeftNoAlign

It is right to left but except Alignment property not reversed, but in Lazarus worked when use FlipControls

bdRightToLeftReadingOnly

It is right to left text reading only, scrollbar and alignment is not take effect.

ParentBidiMode

If it is True the control inherit BidiMode value from the parent.

For BidiMode Developers

When you build you own controls and try make your control support the right to left or BidiMode, you must not access the BiDiMode property directly, you must use

 function UseRightToLeftAlignment: Boolean; virtual;
 function UseRightToLeftReading: Boolean; virtual;
 function UseRightToLeftScrollBar: Boolean;
 function IsRightToLeft: Boolean;

Becuase some controls not need to make effect to the alignment for example TButton it always is centerd , or TMainMenu it always take Right align if it Right To left.


Not just reading the words and cells, it is every thing depend on the order (positions), for application there is a Menus and Controls that placed on the form it must have position from the right.

Sample 1

Add BidiMode support to LCL components

Most of OS now support RightToLeft but there is controls not supported yet or there is controls make by native language like as (TLabel, TGrid). so we have 3 kinds of control

  1. Standard Controls: it easy to make it just add some flag to switch it to RightToLeft (TEdit, TList, TComboBox, TCheckBox).
  2. Standard Controls not supported in OS: There is no idea just waiting the OS developers to implement it to support (TListView, TTreeView), or use native controls already support it.
  3. Native Controls: more hard work for make it Support RightToLeft, or we must add new control already have this features (TLabel, TGrid).

Make application Right to Left order have 4 phases

Phase 1: Add BidiMode property to TControl

TBidiMode already declaired in Classes <delphi>

 property BiDiMode: TBiDiMode read FBiDiMode write SetBiDiMode stored IsBiDiModeStored;
 property ParentBiDiMode: Boolean read FParentBiDiMode write SetParentBiDiMode default True;

</delphi>

BidiMode must not stored if ParentBidiMode = True <delphi>

 function TControl.IsBiDiModeStored: Boolean;
 begin
   Result := not ParentBiDiMode;
 end;

</delphi>

Add virtual functions <delphi>

 function IsRightToLeft:Boolean; virtual;
 function UseRightToLeftAlignment: Boolean; virtual;
 function UseRightToLeftReading: Boolean; virtual;
 function UseRightToLeftScrollBar: Boolean; virtual;

</delphi>

 BiDiMode property in public and must published in every control need to RightToLeft

In delphi there is UseRightToLeftAlignment and UseRightToLeftReading and UseRightToLeftScrollBar but there is a Alignment property in TLabel, TEdit not have but we can implement an Alignment for it, so i will not use this technique for now.

Phase 2: Modify Standard controls that supported by OS

Add RightToLeft to Standard controls,

done here for Win32

TForm {done} 
TLabel {done} Alignment reverse when bdRightToLeft
TButton {done}
TEdit {done}
TListBox {done}
TComboBox {done}
TCheckBox {done}
TStaticText {done}
TGroupBox {done}
TRadioButton {done} (in Win32 need RecreateWnd in SetBidiMode)
TMenu/TMenuItem {done} there is a bug in windows  
   With Menus in Lazarus Win32 the developers force to make it OWNERDRAW, We want to modify DrawMenuItem functions {done}.
TScrollbar {not supported by Win32} Delphi emulate it by change the position with virtual position.


In progress

 TApplication {done} Changing the BidiMode will fire ParentBidiModeChanged and FlipChildren to all TComponent and TControls owned by Application, and also FlipChildrens will reverse the Anchors as like Align property.
Application.AutoFlipControls:Boolean; {not yet}
When Application.AutoFlipControls is True and change the Application.BidiMode value Application object send to all form to FlipControls.
it is useful when changing the language from "Left To Right" language like as English to Arabic and vise versa.
TBitBtn {} Layout glyph will reversed between Right and Left
TSpeedBtn {} Layout glyph will reversed
TRadioGroup {It use ChildSizing more complex code for me and sensitive area}
TCheckGroup 
TGrid {}
 

Delphi use CanvasOrientation for mirror the control and maked RightToLeft, i hate use this because it flip the shadow and images (like as the Check) it is make the control ugly.

Phase 4: Functions and Utils useful for multi language application

 FlipControls; virtual;
 Change Right to Left and Left to Right in this properties (Left, Align, Anchors and Alignment)
 if We compare with Delphi(TM) Anchors and Alignment was excepted
 Need funtion to detect language is RightToLeft.

How to test RightToLeft reading

Create new form, then add TButton or TEdit set the caption to OK? you must add ? or ! or . to the last word with out space, now set the BidiMode to bdRightToLeft, you will see the ? in the left of word.


References

http://www.unicode.org/reports/tr9/