Screen scaffolding: controls: Difference between revisions

From OpenPetra Wiki
Jump to navigation Jump to search
(Deprecated: this only applied to the winforms client)
Tag: Replaced
 
(55 intermediate revisions by 8 users not shown)
Line 1: Line 1:
== Control Hierarchy ==
Deprecated: this only applied to the winforms client
'''Root Control''': Usually, the first Pagecontrl (tab), GroupBox (grp), User contrl (uco), or Panel (pnl). Sometimes, especially with inheritance of the forms, this does not work. So you can set the attribute RootControl=true for the control that you want to be the root. (this behaviour is implemented in Ict.Tools.CodeGeneration.TCodeStorage.GetRootControl)
 
'''Detail''': if you have the word Detail in front of a control name, just after the control prefix, this means that the control belongs to the detail table.
 
'''grdDetails''' and '''pnlDetails''' are special controls which have special meaning for disabling the detail controls etc
 
== Layout of Controls ==
=== Size of Controls ===
* use '''Height'''=200 for setting the height (in pixels) of Controls.
** this will work only on Controls whose height can be influenced - e.g. Panels, GroupBoxes, etc., but not e.g. on CheckBoxes, TextBoxes (unless it is multiline).
* use '''Width'''=200 for setting the width (in pixels) of Controls.
** this will work only on Controls whose width can be influenced - e.g. Panels, GroupBoxes, etc., but not e.g. on CheckBoxes.
''It is possible to specify both Width ''and'' Height attributes, or just Height, but not Width alone!''
* use '''Stretch''' to make a control's width, height, or both, fill the enclosing control's width, height, or both.
** 'Stretch=''horizontally' '' makes a control's width fill the enclosing control's width
** 'Stretch=''vertically' '' makes a control's height fill the enclosing control's height
** 'Stretch=''fully' '' makes a control's height and width fill the enclosing control's height and width.
** if the Control is arranged in a Grid (see below), the 'enclosing control' is substituted with the grid's 'cell' that the Control is placed in.
* use '''Dock'''=Fill, or Dock=Top, or Dock=Bottom.
** if you use a Dock attribute for each control in a container, then it would not use TableLayoutPanel, which might improve the behaviour on Mono (Mono does not cope well with TableLayoutPanel at the moment, Mono 2.4).
 
=== Arranging Controls ===
* use Panels (pnl) or GroupBoxes (grp) to group controls.
** Panels are invisible, whereas GroupBoxes draw a border around the Controls and have a title.
* by default, controls are arranged vertically (each control below the previous control)
** to have the controls in one row (each control to the right of the previous control), use '''ControlsOrientation''' = horizontal
* to arrange controls in a '''Grid'''/Table style, use several RowX, RowY, etc as sub-elements of Controls; the elements of each row are arranged horizontally.
** Tip #1: if you want a 'gap' between columns or rows (i.e. skip a colum or row), put the text 'Empty' in the place where a Control's name would go (this can be in a column or in a row). There needs to be a Control called 'Empty' so the Generator doesn't complain. (Any attributes set on this 'Empty' Control are ignored, since the Control doesn't get generated at all...)
*** if you have the need for several 'empties', name them 'Empty1', 'Empty2', etc. Also name the 'Controls' appropriately.
** Tip #2: if you have the need to arrange Controls in a way that some Controls should go to a place in the TableLayout 'grid' that doesn't exist because of how the Columns are arranged, the simplest way of achieving this might be to place a Panel instead of the first of the Controls that should go on an 'irregular' position. Then arrange the Control(s) within that Panel. You can use the 'Margin' attribute to adjust the exact position of the Panel within the 'grid'. Example: pnlCheckBoxes in Ict\Petra\Client\lib\MPartner\UC_PartnerDetails_Organisation.yaml
** Tip 3: The Width of the Columns of the Grid is determined automatically, as is the height of the Rows. There is a way to override the automatic width/height: use the ColWidths and ColHeight attributes.
*** Example 1: <code>ColWidths: [0=Fixed:140, 1=Fixed:130, 2=Percent:20, 3=Fixed:80]</code>: This assigns fixed widths (in pixels) to the first two and to the fourth column, and defines that Column 3 should take up 20 percent of the width of the whole grid.
*** Example 2: <code>RowHeights: [2=Fixed:35]</code>: This assigns a fixed height (in pixels) to the third Row; all other heights are determined automatically.
** use '''Align'''=right to right-align a control in the grid's column that it is in.
*** By default, all controls are left-aligned, except for the Labels of controls that are auto-generated, those are right-aligned automatically.
** use '''ColSpan'''=''x'' to span a control over ''x'' Columns
** use '''RowSpan'''=''x'' to span a control over ''x'' Rows
 
=== (Automatic) Labels ===
* '''Label''' sets the label for the control, otherwise it is built from the control name, without prefix
* '''NoLabel'''=true will generate the control without a label
* '''VariableLabelText'''=true will not add a translated label for the control, because the label will be set in Manualcode anyway
 
=== Other Attributes ===
* '''ReadOnly'''=true will make a control read-only and also prevents the cursor from jumping into the control if the user 'tabs' through the screen with the <TAB> key.
* '''Enabled'''=false will disable the control. This is useful for prototyping etc. Otherwise, you should link the control with an action, and disable the action depending on the state of the screen
 
=== Different Sizes for Mono/other languages ===
Mono has quite some problems with the TableLayoutManager and AutoSize controls at the moment (Mono 2.4).
 
As well, for other languages the labels of controls might be longer, and we need different sizes for controls.
 
Therefore, you can create for each screen an inherited yaml file, and just define the height and width in pixels. eg, see Client/lib/MFinance/gui/UC_GLTransactions.en.yaml; you need to set the GUI language you want to compile for in the OpenPetra.build.config file.
 
== Attributes for controls on report screens ==
* '''ParameterName''': will use the given name for the parameters that are sent to the server; otherwise it will be built from the control name
* '''ParameterValue''': for radio buttons, assign the value that should be set if this option is selected; otherwise it will be built from the control name, or from the OptionalValues list
* '''NoParameter'''=true: will ignore the control, eg the ledger name text field is read-only, and is only for information
 
== Control Types ==
=== Container Controls ===
==== General ====
* pnl: Panel. Container for any number of any Controls. Use this to logically group controls. Note: a Panel is not visible, unless a 'BackColour' is assigned.
* grp: GroupBox. Container for any number of any Controls. Similar to Panel, but it is visible: it draws a border around its containted controls and displays a title.
* tab: Tab Control. Container for any number of TabPages (tpg). Cannot contain any other kind of Control!
** '''DragTabPageEnabled''': allow rearranging the order of TabPages (default: true)
** '''ShowToolTips''': allows showing of ToolTips on the headers of the TabPages (default: false)
** if '''LoadPagesDynamically''' is true, the Generator creates code that dynamically loads a UserControl for TabPages that have 'LoadPageDynamically' set to true. That code is only executed when the TabPage is switched to for the first time. Using this facility, a programmer can improve the load time of a form that has many controls on many TabPages! (default=false)
* tpg: TabPage of a Tab Control. Container for any number of any Controls. Similar to Panel, but has the appearance of a Tab and has a title.
** '''ToolTip''': defines ToolTip text that should be shown on the header of the TabPage. This is only shown if 'ShowToolTips' is set to true for the TabControl!
** if '''LoadPageDynamically''' is true and 'LoadPage'''s'''Dynamically' of the TabControl is true as well, the Generator creates code that dynamically loads a UserControl that is the only Control on this TabPage. '''DynamicControlType''' needs to be specified in this case. (default=false)
** '''DynamicControlType''' specifies the UserControl that should get dynamically loaded. Only works if 'LoadPageDynamically' of the TabPage is true as well! See example for 'UserControl' for the value. Example:
        tpgAddresses:
            LoadPageDynamically: true
            DynamicControlType: Ict.Petra.Client.MCommon.TUCPartnerAddresses
* uco: UserControl. UserControls can be understood as 'sub-forms' or simply parts of a screen whose layout is specified separately from the screen.
** needs attribute 'Type' with the value containing the full namespace for the control, e.g.
        ucoPersonnelTabSet:
            Type: Ict.Petra.Client.MPartner.Gui.TUC_PartnerEdit_PersonnelTabSet
 
==== Specialised ====
* spt: SplitContainer. Divides a part of the screen either horizontally or vertically and shows a 'Splitter line' between them. The user can 'drag' the 'Splitter line' with the mouse and give more or less space to controls on either side of the line.
** '''SplitterOrientation'''. Supported values are: 'vertical', 'horizontal'.
** '''SplitterDistance''' specified the Width or Height of the first Panel in pixels.
**'''Panel1''' and '''Panel2''' refer to one control only at the moment.
* rgr: RadioButton group.
** Can contain several other Controls in 'Controls' list, which will create RadioButtons with the Controls for each item.
** Alternatively it can just contain text in value 'OptionalValues', which will create RadioButtons for each text.
** Controls within the RadioButton group are Enabled/Disabled automatically: the Control whose RadioButton is 'active' within the RadioButton group is automatically enabled, all other Controls within the RadioButton Group are getting automatically disabled.
** for Reports only
*** '''ParameterValue''' can be specified for each RadioButton. This sets a unique value that is independent of the Label of the RadioButton (''therefore it is also translation independent!'')
* rng: Range. Used for entering two values that define a range.
** this is basically a special Panel.
 
=== Basic Controls ===
==== Edit Controls ====
* txt: TextBox. A normal edit field (but see 'Format' and 'Type' below for different behaviours).
** use '''TextAlign''' to align text in the TextBox. Supported values are: Left, Right, Center (default=Left).
** use '''CharacterCasing''' to make the text typed appear in a certain character casing. Supported values are: 'Upper' (for all-uppercase), 'Lower' (for all-lowercase), 'Normal' (for showing the text as typed). Default=Normal.
** use '''PasswordEntry'''=true to prevent any characters that are typed from being shown and show a mask symbol instead of the characters (default=false).
** use '''Multiline'''=true to allow text entry in more than one line of text. To determine the height of the TextBox, use 'Height'. Make sure you assign 'Height', otherwise the TextBox will still appear in its default height, which makes it appear single-line (default=false).
*** if 'Multiline' is true, use '''ScrollBars''' to determine which scrollbars should appear. Supported values are: 'Horizontal', 'Vertical', 'Both', 'None' (default=none).
*** if 'Multiline' is true, use '''WordWrap'''=false to automatically scroll horizontally when the user types past the right edge of the control (default=true).
** use '''Format''' to restrict the characters that can be entered and to turn on specific formatting of the content
*** Supported values are: 'Integer', 'Decimal', 'Currency'.
**** 'Integer' restricts the data entry to numbers (positive and negative) without decimals. No special formatting is done.
**** 'Decimal' and 'Currency' restrict the data entry to numbers (positive and negative) with two decimals. To change the number of decimals, use the format 'Decimal(''x'')' or 'Currency(''x'')', where ''x'' is the number of decimals that should be allowed.
***** 'Decimal' formats the number with a decimal point and thousands separators.
***** 'Currency' formats the number with a decimal point and thousands separators, and shows a Currency Symbol. This is by default '###' and needs to be changed in the ManualCode.cs file by setting the 'CurrencySymbol' Property of the Control.
*** Should the user be allowed to leave the number-only-TextBox empty, set the 'NullValueAllowed' attribute to 'true'. Otherwise the Control will default to '0' (Integer) or '0.00' (Decimal) or '### 0.00' (Currency) when the user empties the Control and moves the Cursor to another Control.
** use '''Type''' to turn on a special layout and behaviour: If a supported value is assigned, the TextBox gets a 'Find' button to its left and a label to the right. The Find Button launches a find screen to look up valid values (or to look up Partners, in case of 'PartnerKey') and the label shows the description of the value (or the 'ShortName' of a Partner in case of 'PartnerKey'). Supported Values are: 'PartnerKey', 'Extract', 'Occupation'. More values can be added; contact us if you need more lookups and we can tell you how to add them.
* chk: CheckBox
** use ''CheckBoxAttachedLabel'' to optionally have a Label directly attached to the CheckBox. This Label can be displayed left or right of the CheckBox Control. The value of 'CheckBoxAttachedLabel' can be 'right' or 'left', depending on which side of the CheckBox the Label should appear.
*** This is not to be confused with the Label that is automatically generated for e.g. TextBoxes and CheckBoxes which is placed in the preceding 'column' of the generated layout. The directly attached Label goes into the same 'colum' as the CheckBox!
** A CheckBox can have a list of dependent other controls in an optional 'Controls' list. Those Controls get enabled when the tick mark is displayed in the CheckBox and disabled if the tick mark isn't displayed.
* nud: Numeric Up/Down
** has a second label '''LabelUnit''', which can be optionally set
** use '''PositiveValueActivates''' to enable a condition when a positive value is selected
* rbt: simple RadioButton
** see also: RadioButton group
* cmb: ComboBox (DropDown). A TextBox with a button that opens a list underneath from which values can be chosen. (Usually uses our custom control Ict.Common.Controls.TCmbAutoComplete.)
** see also [[GUI_development#Overview_Comboboxes|Overview Comboboxes]]
** attribute '''OptionalValues''' defines the values of the combobox; prepend the default option with equals sign
*** sample: <code>OptionalValues: [=Days, Weeks, Months]</code>
** attribute '''List''': this will load the values from the server (and use a cache as well); it will use cmbAutoPopulatedComboBox instead of TCmbAutoComplete
*** possible values for list: eg. CurrencyCodeList
*** sample: <code>cmbCurrency: {Label=&Currency, DataField=AApSupplier.CurrencyCode, List=CurrencyCodeList}</code>
** attribute '''AutoComplete''': this will store the entered search strings in the user defaults
*** <code>cmbSupplierCode: {Label=S&earch Supplier, AutoComplete=SupplierSearchHistory, Tooltip=Search by supplier name or partner key}</code>
** attribute: '''MultiColumn''': this will generate a TCmbVersatile combobox with several columns; make sure to set the column width of the second or more columns, otherwise they will not be visible! (not used yet anywhere)
 
==== Other Controls ====
* lbl: Label. Displays text. Labels are automatically generated for TextBoxes, unless the value '''NoLabel''' is specified for a TextBox.
* btn: Button.
** use '''Action''' to specify the Action that should be executed when the Button is clicked/pressed.
 
=== Advanced Controls ===
* grd: Grid control
** ''the control needs to have the special name "grdDetails" for Master/Detail scenarios''.
** use '''SelectedRowActivates''' to enable a condition when a row is selected.
** use event '''ActionFocusRow''' that is called when the selection of the current row changes.
** use event '''ActionDoubleClick''' to launch an Action when the user double-clicks on a row.
** property '''SortOrder''' defines which column should be sorted. Several columns can be separated by commas; it is necessary to add DESC or ASC; example: <code>SortOrder: ABatch.BatchNumber DESC</code>
** property '''TableName''' makes the list in '''Columns''' shorter.
** property '''Columns''' lists the columns to be displayed.
** property '''CustomColumns''': allows custom column title or custom format to be specified (the 'CustomColumns' property needs to be on the same indent level as the 'Columns' property. Example:
CustomColumns:
    Tagged: {Label=, Type=Boolean}
    DateDue: {Label=Date Due, Type=DateTime}
* trv: TreeView
 
=== Printing ===
* ppv: PrintPreview. This is currently only used internally, by the PrintPreviewWithToolbar
* pre: PrintPreview With Toolbar: this is used with the windowBrowsePrint template. a toolbar is added with current page, number of all pages, buttons for previous and next page, and print current page and general print button.
 
=== ToolBars ===
* tbb: ToolBar Button
* tbl: ToolBar Label
* ttx: ToolBar TextBox
* cmb: ToolBar ComboBox
** '''Width''' specifies the width of the ComboBox in pixels.
 
== Data Binding ==
We don't use .Net databinding, but the generator wires the data.
* You can use the attributes '''MasterTable''' and '''DetailTable''' that will try to match each control to the field in the table with the same name (detail fields must be called &lt;prefix&gt;Detail&lt;fieldname&gt;, eg. txtDetailAmount)
* You can specifically bind data with '''DataField''', either with the data table name or just the field name.
** sample: <code>DataField=AApSupplier.CurrencyCode</code>
* For some controls, eg radiobuttons used for filtering the displayed data, you need to avoid that the Save button gets activated: use '''SuppressChangeDetection''': true
=== special lookups ===
* '''PartnerShortNameLookup''': this is for printing the partner short name on a screen; usually this is read-only; but you need to specify that with '''ReadOnly=true'''
** sample: <code>txtSupplierName: {Label=Current Supplier, ReadOnly=true, PartnerShortNameLookup=AApDocument.PartnerKey}</code>
 
=== special behaviour ===
* if you link a boolean database field to a combobox with 2 values, it will match the value (first value is false, second value is true).
** sample: <br/> <code>OptionalValues: [=Invoice, Credit Note]<br/>DataField: CreditNoteFlag</code>
 
== Events ==
* attribute '''OnChange''' points to a function that is called if the value in the control changes
** sample: <code>dtpDateIssued: {Label=&Date Issued, OnChange=UpdateCreditTerms}</code>
** This applies the same to all kinds of Controls, although the Events of various Controls which denote a 'change' are indeed different. The Generator hooks up the following Events for you when the attribute ''OnChange'' is used:
*** For all Controls other than the ones listed below: the 'ValueChanged' Event is hooked up.
*** TextBox: the 'TextChanged' Event is hooked up.
**** This Event is fired ''while typing''! (If you want an Event that is fired after all characters have been typed, use ''OnLeave''.)
*** ComboBox/DropDown: the 'SelectedValueChanged' Event is hooked up.
*** CheckBox and RadioButton: the 'CheckedChanged' Event is hooked up.
*** DateTimePicker: the 'DateChanged' is hooked up.
* attribute '''OnLeave''' points to a function that is called once a Control is left
** sample: <code>txtDetailTimeZoneMinimum: {Label=Time Zone From, OnLeave=UpdateTimeZoneMaximum}</code>
** This applies the same to all kinds of Controls
** OnLeave is executed no matter how the Control is left (e.g. by using the <Tab> key, using the mouse, or by keyboard shortcut) - with one exception: it is not executed if a user clicks on a ToolBarButton!
* attribute '''Action''' points to an action that is executed for Click etc
** actually, there is now a convention, ie. the name of the control matches the name of the action, and the sample would not be even necessary
** sample: <code>mniNewSupplier: {Action=actNewSupplier}</code>
* attribute '''ActionClick'''/'''ActionDoubleClick''' points to a function that is called if the control is clicked
** sample: <code>grdSupplierResult: {Dock=Fill, ActionDoubleClick=actSupplierTransactions, SelectedRowActivates=cndSelectedSupplier}</code>
* attribute '''ActionOpenScreen''' will open a screen (defined with full namespace); if '''PropertyForSubScreens''' is set for the form, and the new screen has that propery too, it will be assigned
** sample: <code>mniAccountsPayable: {Label=&Accounts Payable, ActionOpenScreen=Ict.Petra.Client.MFinance.Gui.AccountsPayable.TFrmAPMain}</code>
* in a grid: attribute '''SelectedRowActivates''': activate a condition/action, which other actions can depend on
* in a grid: '''ActionFocusRow''' is called when the selection of the current row changes

Latest revision as of 03:48, 22 Haziran 2023

Deprecated: this only applied to the winforms client