mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-08-18 09:48:10 +08:00
...
This commit is contained in:
@@ -646,6 +646,13 @@ It provides a comprehensive testing framework, XML-to-C++ compilation, and integ
|
||||
- [Using Streams](./manual/vlppos/using-streams.md)
|
||||
- [Using Threads and Locks](./manual/vlppos/using-threads.md)
|
||||
|
||||
## Vlpp Parser2
|
||||
|
||||
- [AST Definition](./manual/vlppparser2/ast.md)
|
||||
- [Lexer Definition](./manual/vlppparser2/lexer.md)
|
||||
- [Syntax Definition](./manual/vlppparser2/syntax.md)
|
||||
- [Generated APIs](./manual/vlppparser2/apis.md)
|
||||
|
||||
## Workflow Script
|
||||
|
||||
- [Running a Script](./manual/workflow/running.md)
|
||||
|
||||
@@ -1,56 +1,78 @@
|
||||
# ALT Sequence and Control Focus
|
||||
|
||||
If a focusable control is put on a window, by setting the [Alt](../.././gacui/components/controls/basic/home.md) property to a value, for example "X", then it could get focused by pressing **ALT** followed by **X** (not **ALT+X**).
|
||||
If a focusable control is put on a window, by setting the[Alt](../.././gacui/components/controls/basic/home.md)property to a value, for example "X", then it could get focused by pressing**ALT**followed by**X**(not**ALT+X**).
|
||||
|
||||
The **Alt** property could accept a sequence of characters, not just one. Characters in such a sequence needs to be entered to activate this control.
|
||||
The**Alt**property could accept a sequence of characters, not just one. Characters in such a sequence needs to be entered to activate this control.
|
||||
|
||||
If **ESC** is pressed, it goes back to the previous container.
|
||||
If**ESC**is pressed, it goes back to the previous container.
|
||||
|
||||
If **BACKSPACE** is pressed, it cancels the last character in the sequence.
|
||||
If**BACKSPACE**is pressed, it cancels the last character in the sequence.
|
||||
|
||||
When **ALT** is pressed, all valid **ALT** sequences will be printed on the window. All labels rendering these sequences will get changed
|
||||
When**ALT**is pressed, all valid**ALT**sequences will be printed on the window. All labels rendering these sequences will get changed
|
||||
|
||||
## Example
|
||||
|
||||

|
||||
|
||||
The operation is done by pressing the following keys: - **ALT**: Enter the ALT sequence mode. - **P**: There are two controls with the **Alt** property set to "P". It filters them out and wait for a number key. - **0**: The dropdown button is activated, a sub menu is opened. - **ESC**: Close the sub menu and go back to the previous container, which is the window. - **P**: Filter again. - **BACKSPACE**: Cancel the last character "P" in the sequence, showing all available items. - **P**: Filter again. - **1**: The paste button is activated, a piece of text get pasted to the editor. The ALT sequence mode is exited because an item is finally chosen. - **ALT**: Enter the ALT sequence mode. - **D**: Give the focus to the editor control. - **CTRL+A**: Select all text. - **DELETE**: Delete the selection.
|
||||
The operation is done by pressing the following keys:
|
||||
- **ALT**: Enter the ALT sequence mode.
|
||||
- **P**: There are two controls with the**Alt**property set to "P". It filters them out and wait for a number key.
|
||||
- **0**: The dropdown button is activated, a sub menu is opened.
|
||||
- **ESC**: Close the sub menu and go back to the previous container, which is the window.
|
||||
- **P**: Filter again.
|
||||
- **BACKSPACE**: Cancel the last character "P" in the sequence, showing all available items.
|
||||
- **P**: Filter again.
|
||||
- **1**: The paste button is activated, a piece of text get pasted to the editor. The ALT sequence mode is exited because an item is finally chosen.
|
||||
- **ALT**: Enter the ALT sequence mode.
|
||||
- **D**: Give the focus to the editor control.
|
||||
- **CTRL+A**: Select all text.
|
||||
- **DELETE**: Delete the selection.
|
||||
|
||||
## Behavior after being Focused
|
||||
|
||||
There are three kinds of behaviors when a control is focused by a **ALT** sequence. If a control is focused by **TAB**, it could behaves differently. - `empty list item` **Just being focused** Controls with complex keyboard behaviors like editors or list controls, will just get focused and do nothing else. - `empty list item` **Execute a Command** Controls with simple executable behaviors like buttons, will do what it does when clicked, after being focused by an **ALT** sequence. - `empty list item` **Just being focused** Controls that are not executable but contains executable items, like menu items with a sub menu, will render all executable items after being focused by an **ALT** sequence. A menu item with a sub menu does nothing when it is clicked. But if it is activated by an **ALT** sequence, the sub menu will be opened and wait for more keys.
|
||||
There are three kinds of behaviors when a control is focused by a**ALT**sequence. If a control is focused by**TAB**, it could behaves differently.
|
||||
- `empty list item`
|
||||
**Just being focused**
|
||||
Controls with complex keyboard behaviors like editors or list controls, will just get focused and do nothing else.
|
||||
- `empty list item`
|
||||
**Execute a Command**
|
||||
Controls with simple executable behaviors like buttons, will do what it does when clicked, after being focused by an**ALT**sequence.
|
||||
- `empty list item`
|
||||
**Just being focused**
|
||||
Controls that are not executable but contains executable items, like menu items with a sub menu, will render all executable items after being focused by an**ALT**sequence.
|
||||
A menu item with a sub menu does nothing when it is clicked. But if it is activated by an**ALT**sequence, the sub menu will be opened and wait for more keys.
|
||||
|
||||
## Create your own Behavior
|
||||
|
||||
If a new control class is created, there are multiple ways to customize the behavior about how a control should react to an **ALT** sequence:
|
||||
If a new control class is created, there are multiple ways to customize the behavior about how a control should react to an**ALT**sequence:
|
||||
|
||||
### Using IGuiAltAction
|
||||
|
||||
**IGuiAltAction** is a protected base class of all controls. If a new control is created, methods could be overriden.
|
||||
**IGuiAltAction**is a protected base class of all controls. If a new control is created, methods could be overriden.
|
||||
|
||||
Properly assigning an **ALT** sequence to the **Alt** property of a control could also make these methods behave as expected easily. **IsAltEnabled** returns **true** if the control is visible and enabled. **IsAltAvailable** returns **true** if the control is focusable and the **Alt** property is not empty.
|
||||
Properly assigning an**ALT**sequence to the**Alt**property of a control could also make these methods behave as expected easily.**IsAltEnabled**returns**true**if the control is visible and enabled.**IsAltAvailable**returns**true**if the control is focusable and the**Alt**property is not empty.
|
||||
|
||||
When the window is in the **ALT** sequence mode, a label rendering the sequence for this control will be put in the composition from **GetAltComposition**.
|
||||
When the window is in the**ALT**sequence mode, a label rendering the sequence for this control will be put in the composition from**GetAltComposition**.
|
||||
|
||||
If both **IsAltEnabled** and **IsAltAvailable** returns **true**, then the result of **GetAlt()**, which is also the value from the **Alt** property by default, becomes one of an candidate. **OnActiveAlt** will be called when this control is selected by a **ALT** sequence.
|
||||
If both**IsAltEnabled**and**IsAltAvailable**returns**true**, then the result of**GetAlt()**, which is also the value from the**Alt**property by default, becomes one of an candidate.**OnActiveAlt**will be called when this control is selected by a**ALT**sequence.
|
||||
|
||||
### Using IGuiAltActionContainer
|
||||
|
||||
**IGuiAltActionContainer** is a [ service object ](../.././gacui/components/controls/basic/home.md). A service object could be attached to a control by calling **AddService** or overriding **QueryService**.
|
||||
**IGuiAltActionContainer**is a[service object](../.././gacui/components/controls/basic/home.md). A service object could be attached to a control by calling**AddService**or overriding**QueryService**.
|
||||
|
||||
If an **IGuiAltActionContainer** instance is attached to a control, then all methods in **IGuiAltAction** are ignored. Instead, multiple **IGuiAltAction** object returned from this interface will be used.
|
||||
If an**IGuiAltActionContainer**instance is attached to a control, then all methods in**IGuiAltAction**are ignored. Instead, multiple**IGuiAltAction**object returned from this interface will be used.
|
||||
|
||||
You could now assign multiple **ALT** sequence to a control, with each sequence binded to a different behavior.
|
||||
You could now assign multiple**ALT**sequence to a control, with each sequence binded to a different behavior.
|
||||
|
||||
All **IGuiAltAction** returned from **IGuiAltActionContainer** must be enabled and available.
|
||||
All**IGuiAltAction**returned from**IGuiAltActionContainer**must be enabled and available.
|
||||
|
||||
### Using IGuiAltActionHost
|
||||
|
||||
An **IGuiAltActionHost** instance could be attached to a control by calling **SetActivatingAltHost** or overriding **GetActivatingAltHost**.
|
||||
An**IGuiAltActionHost**instance could be attached to a control by calling**SetActivatingAltHost**or overriding**GetActivatingAltHost**.
|
||||
|
||||
When a control is selected by a **ALT** sequence, if **IGuiAltActionHost** is attached to this control, then the **ALT** sequence mode will not exit. Instead, this **IGuiAltActionHost** is treated as a nested container, and GacUI calls **CollectAltActions** to collect all valid **IGuiAltAction**, renders all **ALT** and wait for keyboard input.
|
||||
When a control is selected by a**ALT**sequence, if**IGuiAltActionHost**is attached to this control, then the**ALT**sequence mode will not exit. Instead, this**IGuiAltActionHost**is treated as a nested container, and GacUI calls**CollectAltActions**to collect all valid**IGuiAltAction**, renders all**ALT**and wait for keyboard input.
|
||||
|
||||
All top level controls like a window or a menu are attached by an **IGuiAltActionHost** by default. If a sub menu is created on a menu item, **IGuiAltActionHost** is attached to this control. So when it is activated, it opens the sub menu and continue to wait for more keys, instead of executing this menu item.
|
||||
All top level controls like a window or a menu are attached by an**IGuiAltActionHost**by default. If a sub menu is created on a menu item,**IGuiAltActionHost**is attached to this control. So when it is activated, it opens the sub menu and continue to wait for more keys, instead of executing this menu item.
|
||||
|
||||
**GuiAltActionHostBase** is the default implementation of **IGuiAltActionHost**. If it is attached to a control, all child controls with valid **IGuiAltAction** are not visible from the container, instead they are available when the parent control is selected by an **ALT** sequence. **GuiAltActionHostBase::SetAltControl** must be called to initialize this class, it tells this implementation where to search for child controls to collect **IGuiAltAction**.
|
||||
**GuiAltActionHostBase**is the default implementation of**IGuiAltActionHost**. If it is attached to a control, all child controls with valid**IGuiAltAction**are not visible from the container, instead they are available when the parent control is selected by an**ALT**sequence.**GuiAltActionHostBase::SetAltControl**must be called to initialize this class, it tells this implementation where to search for child controls to collect**IGuiAltAction**.
|
||||
|
||||
|
||||
@@ -1,46 +1,89 @@
|
||||
# Animations
|
||||
|
||||
The GacUI XML [<Animation/>](../.././gacui/xmlres/tag_animation.md) resource creates helper classes for animations. It creates a class like this: ``` class MyAnimation { prop Current: STATE_CLASS^{} new (current: STATE_CLASS^){} func CreateAnimation(target: STATE_CLASS^, time: UInt64); } ``` **STATE_CLASS** is a class with fields of number types or **Color**. By creating an **MyAnimation^** in a window like this: ``` <Instance ...> <ref.Members><![CDATA[ var myAnimation : MyAnimation^ = new MyAnimation(initial_state); ]]></ref.Members> <Window ref.Name="self"> <Something PropertyToAnimate-bind="self.myAnimation.Current.FIELD"/> </Window> </Instance> ``` You are able to bind the expression **self.myAnimation.Current.FIELD** to any compatible property. When the animation is running, fields in **self.myAnimation.Current** will keep updating, so that to animate the UI.
|
||||
The GacUI XML[<Animation/>](../.././gacui/xmlres/tag_animation.md)resource creates helper classes for animations. It creates a class like this:
|
||||
```
|
||||
class MyAnimation
|
||||
{
|
||||
prop Current: STATE_CLASS^{}
|
||||
new (current: STATE_CLASS^){}
|
||||
func CreateAnimation(target: STATE_CLASS^, time: UInt64);
|
||||
}
|
||||
```
|
||||
**STATE_CLASS**is a class with fields of number types or**Color**. By creating an**MyAnimation^**in a window like this:
|
||||
```
|
||||
<Instance ...>
|
||||
<ref.Members><![CDATA[
|
||||
var myAnimation : MyAnimation^ = new MyAnimation(initial_state);
|
||||
]]></ref.Members>
|
||||
<Window ref.Name="self">
|
||||
<Something PropertyToAnimate-bind="self.myAnimation.Current.FIELD"/>
|
||||
</Window>
|
||||
</Instance>
|
||||
```
|
||||
You are able to bind the expression**self.myAnimation.Current.FIELD**to any compatible property. When the animation is running, fields in**self.myAnimation.Current**will keep updating, so that to animate the UI.
|
||||
|
||||
## Interpolation Functions
|
||||
|
||||
The first step to animate a field in **self.myAnimation.Current** is to set a proper interpolation function, which is described in [<Animation/>](../.././gacui/xmlres/tag_animation.md). Only fields that mentioned by a **\<Target/\>** tag could be animated. All animated fields must associate an interpolation function. There is also a place for a default interpolation function, which will apply on all animated fields unless one is specified in **\<Target/\>**.
|
||||
The first step to animate a field in**self.myAnimation.Current**is to set a proper interpolation function, which is described in[<Animation/>](../.././gacui/xmlres/tag_animation.md). Only fields that mentioned by a**\<Target/\>**tag could be animated. All animated fields must associate an interpolation function. There is also a place for a default interpolation function, which will apply on all animated fields unless one is specified in**\<Target/\>**.
|
||||
|
||||
An interpolation function is an Workflow expression in a function type, which takes a **double** and returns a **double**.
|
||||
An interpolation function is an Workflow expression in a function type, which takes a**double**and returns a**double**.
|
||||
|
||||
The function parameter is the progress of the animation from **0** to **1**. If an animation is 10 seconds long, then **0** is the beginning, **1** is the ending, and **0.4** means **10 seconds * 0.4** which is at the end of the 4th second.
|
||||
The function parameter is the progress of the animation from**0**to**1**. If an animation is 10 seconds long, then**0**is the beginning,**1**is the ending, and**0.4**means**10 seconds * 0.4**which is at the end of the 4th second.
|
||||
|
||||
The return value is the interpolation of the animation from **0** to **1**. If the begin state is **5** and the end state is **15**, then returning **0** means **5**, returning **1** means **15**, and returning **0.4** means the **5 + (15 - 5) * 0.4** which is **9**.
|
||||
The return value is the interpolation of the animation from**0**to**1**. If the begin state is**5**and the end state is**15**, then returning**0**means**5**, returning**1**means**15**, and returning**0.4**means the**5 + (15 - 5) * 0.4**which is**9**.
|
||||
|
||||
The interpolation calculate that, where a field should go given the progress of the animation. If a linear interpolation function is expected, then just return the parameter. Such a function would typically be:
|
||||
- for[ordered lambda expression](../.././workflow/lang/expr.md):**[$1]**
|
||||
- for[lambda expression](../.././workflow/lang/expr.md): for example:**func (progress: double) : double { return progress; }**Sometimes it is better to make the field accelerate at the first half and decelerate at the second half, such a function could be easily created using:
|
||||
```
|
||||
func (x: double): double
|
||||
{
|
||||
if (x < 0.5) { return x * x * 2; } else { return 1 - (1 - x) * (1 - x) * 2; }
|
||||
}
|
||||
```
|
||||
|
||||
The interpolation calculate that, where a field should go given the progress of the animation. If a linear interpolation function is expected, then just return the parameter. Such a function would typically be: - for [ordered lambda expression](../.././workflow/lang/expr.md) : **[$1]** - for [lambda expression](../.././workflow/lang/expr.md) : for example: **func (progress: double) : double { return progress; }** Sometimes it is better to make the field accelerate at the first half and decelerate at the second half, such a function could be easily created using: ``` func (x: double): double { if (x < 0.5) { return x * x * 2; } else { return 1 - (1 - x) * (1 - x) * 2; } } ```
|
||||
|
||||
## Running an Animation
|
||||
|
||||
In the **\<Animation/\>** generated class, there is a **CreateAnimation(state, time)** function, which means the animation begins from the current state, and run towards **state** in **time** milliseconds.
|
||||
In the**\<Animation/\>**generated class, there is a**CreateAnimation(state, time)**function, which means the animation begins from the current state, and run towards**state**in**time**milliseconds.
|
||||
|
||||
Calling this function doesn't make the animation run, instead it returns an **(vl::)presentation::controls::IGuiAnimation^** object. **AddAnimation** and **KillAnimation** of **(vl::)presentation::controls::GuiInstanceRootObject** controls how the animation run. This class is the base class for all UI [ root instances ](../.././gacui/xmlres/instance/root_instance.md), so **AddAnimation** and **KillAnimation**, or **self.AddAnimation** and **self.KillAnimation**, are accessible in the XML.
|
||||
Calling this function doesn't make the animation run, instead it returns an**(vl::)presentation::controls::IGuiAnimation^**object.**AddAnimation**and**KillAnimation**of**(vl::)presentation::controls::GuiInstanceRootObject**controls how the animation run. This class is the base class for all UI[root instances](../.././gacui/xmlres/instance/root_instance.md), so**AddAnimation**and**KillAnimation**, or**self.AddAnimation**and**self.KillAnimation**, are accessible in the XML.
|
||||
|
||||
**AddAnimation** adds an **IGuiAnimation** object to the UI object, and start the animation immediately.
|
||||
**AddAnimation**adds an**IGuiAnimation**object to the UI object, and start the animation immediately.
|
||||
|
||||
**KillAnimation** stops an **IGuiAnimation** object that has been added to the UI object, and stop the animation immediately.
|
||||
**KillAnimation**stops an**IGuiAnimation**object that has been added to the UI object, and stop the animation immediately.
|
||||
|
||||
For animations that need to switch from state to state for multiple times, like a button when the mouse is moving in and out, there is a pattern to control the animation: ``` <ref.Members><![CDATA[ var myAnimation : MyAnimation^ = new MyAnimation(initial_state); var lastAnimation : IGuiAnimation^ = null; ]]></ref.Members> ... var newAnimation = myAnimation.CreateAnimation(newState, animationLengthInMilliseconds); KillAnimation(lastAnimation); lastAnimation = newAnimation; AddAnimation(lastAnimation); ``` When the state needs to move to a new state when the animation is running, this piece of code stops the current running animation, and replace it with a new one. The new animation moves the current state from where it is to a new state, and it should look smooth.
|
||||
For animations that need to switch from state to state for multiple times, like a button when the mouse is moving in and out, there is a pattern to control the animation:
|
||||
```
|
||||
<ref.Members><![CDATA[
|
||||
var myAnimation : MyAnimation^ = new MyAnimation(initial_state);
|
||||
var lastAnimation : IGuiAnimation^ = null;
|
||||
]]></ref.Members>
|
||||
...
|
||||
var newAnimation = myAnimation.CreateAnimation(newState, animationLengthInMilliseconds);
|
||||
KillAnimation(lastAnimation);
|
||||
lastAnimation = newAnimation;
|
||||
AddAnimation(lastAnimation);
|
||||
```
|
||||
When the state needs to move to a new state when the animation is running, this piece of code stops the current running animation, and replace it with a new one. The new animation moves the current state from where it is to a new state, and it should look smooth.
|
||||
|
||||
**KillAnimation** could accept **null**, and it does nothing.
|
||||
**KillAnimation**could accept**null**, and it does nothing.
|
||||
|
||||
## Managing Multiple Animations
|
||||
|
||||
It is easy to copy the above pattern multiple times for each animation.
|
||||
|
||||
Please remember that, the created **lastAnimation** will change **myAnimation.Current.FIELD** when it is executing, so if multiple animation needs to run at the same time, multiple **lastAnimation** and **myAnimation** should be created at the same time. Please give them good names to make the code looks clear.
|
||||
Please remember that, the created**lastAnimation**will change**myAnimation.Current.FIELD**when it is executing, so if multiple animation needs to run at the same time, multiple**lastAnimation**and**myAnimation**should be created at the same time. Please give them good names to make the code looks clear.
|
||||
|
||||
When a UI object is disposing, e.g. when the close button on a window is clicked, all animations will be shut down, and calling **AddAnimation** will result in an exception.
|
||||
When a UI object is disposing, e.g. when the close button on a window is clicked, all animations will be shut down, and calling**AddAnimation**will result in an exception.
|
||||
|
||||
It is function idential to split all fields to multiple animation objects. But if multiple fields represent different parts of the same animation, do your best to make one animation for all these fields to increase the performance.
|
||||
|
||||
In [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/kb_animation/Resource.xml), a button is controlled by 4 colors, which changes in one animation because they represent different parts of the same animation. So only one **\<Animation/\>** and only one instance of it is needed for one button.
|
||||
In[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/kb_animation/Resource.xml), a button is controlled by 4 colors, which changes in one animation because they represent different parts of the same animation. So only one**\<Animation/\>**and only one instance of it is needed for one button.
|
||||
|
||||
Here is how it looks like:
|
||||
|
||||
- Source code: [kb_animation](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/kb_animation/Resource.xml) - 
|
||||
|
||||
- Source code:[kb_animation](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/kb_animation/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,18 +1,35 @@
|
||||
# Data Bindings
|
||||
|
||||
Data bindings in GacUI relies on [Workflow expression](../.././workflow/lang/bind.md). Basically, an expression is observable if it uses properties, and these properties must be observable by having their property changing events on the object. You are still able to combine some events on a property temporary just for this expression to make it observable.
|
||||
Data bindings in GacUI relies on[Workflow expression](../.././workflow/lang/bind.md). Basically, an expression is observable if it uses properties, and these properties must be observable by having their property changing events on the object. You are still able to combine some events on a property temporary just for this expression to make it observable.
|
||||
|
||||
In GacUI XML Resource, [-bind](../.././gacui/xmlres/instance/properties.md), [-format](../.././gacui/xmlres/instance/properties.md) and [-str](../.././gacui/xmlres/instance/properties.md) are based on data bindings.
|
||||
In GacUI XML Resource,[-bind](../.././gacui/xmlres/instance/properties.md),[-format](../.././gacui/xmlres/instance/properties.md)and[-str](../.././gacui/xmlres/instance/properties.md)are based on data bindings.
|
||||
|
||||
## Binding to Control Properties
|
||||
|
||||
This is the most basic kind of data binding.
|
||||
|
||||
If you are binding something to a text property which will be displayed on the UI, e.g. **Text** of a **\<Label/\>**, make sure that: - The layout of controls is properly handled, so that they will re-arrange themselves to make sure that no truncation of text rendering will happen. - If the application could be send to people using different language, please consider using **Localization** from the very beginning.
|
||||
If you are binding something to a text property which will be displayed on the UI, e.g.**Text**of a**\<Label/\>**, make sure that:
|
||||
- The layout of controls is properly handled, so that they will re-arrange themselves to make sure that no truncation of text rendering will happen.
|
||||
- If the application could be send to people using different language, please consider using**Localization**from the very beginning.
|
||||
|
||||
Binding view models to control is also very straight-forward. A **\<ref.Paramter Name="Something" Class="..."/\>** creates a property that will never change once the window is created. The **X** property of **Something** can be binded to a control property just by: ``` <AControl AProperty-bind="Something.X"/> ```
|
||||
Binding view models to control is also very straight-forward. A**\<ref.Paramter Name="Something" Class="..."/\>**creates a property that will never change once the window is created. The**X**property of**Something**can be binded to a control property just by:
|
||||
```
|
||||
<AControl AProperty-bind="Something.X"/>
|
||||
```
|
||||
|
||||
It is also very simple to use data binding with your own objects like: ``` <Instance ref.Class="..."> <ref.Members><![CDATA[ var myObject = new MyObject(); ]]></ref.Members> <Window ref.Name="self"> <AControl AProperty-bind="self.myObject.X"/> </Window> </Instance> ``` Since **myObject** is a member of the window, you must first give the window a name **self**, to make XML knows what is **myObject**.
|
||||
|
||||
It is also very simple to use data binding with your own objects like:
|
||||
```
|
||||
<Instance ref.Class="...">
|
||||
<ref.Members><![CDATA[
|
||||
var myObject = new MyObject();
|
||||
]]></ref.Members>
|
||||
<Window ref.Name="self">
|
||||
<AControl AProperty-bind="self.myObject.X"/>
|
||||
</Window>
|
||||
</Instance>
|
||||
```
|
||||
Since**myObject**is a member of the window, you must first give the window a name**self**, to make XML knows what is**myObject**.
|
||||
|
||||
## Binding between Composition Properties
|
||||
|
||||
@@ -20,27 +37,79 @@ It is also very simple to use data binding with your own objects like: ``` <Inst
|
||||
|
||||
The built-in layout algorithm already make compositions bidirectionally react to each other. Binding one property in a composition to another property in (maybe) another composition could cause the reaction never end.
|
||||
|
||||
Here is a very bad example: ``` <Bounds ref.Name="parent" MinSizeLimitation="LimitToElementAndChildren"> <Bounds ref.Name="child" PreferredMinSize-bind="{x:(parent.Bounds.x2 - parent.Bounds.x1} y:0}" AlignmentToParent="{left:1 top:1 right:1 bottom:1}" /> </Bounds> ```
|
||||
Here is a very bad example:
|
||||
```
|
||||
<Bounds ref.Name="parent" MinSizeLimitation="LimitToElementAndChildren">
|
||||
<Bounds ref.Name="child"
|
||||
PreferredMinSize-bind="{x:(parent.Bounds.x2 - parent.Bounds.x1} y:0}"
|
||||
AlignmentToParent="{left:1 top:1 right:1 bottom:1}"
|
||||
/>
|
||||
</Bounds>
|
||||
```
|
||||
|
||||
When **parent.Bounds** is changed, the observed expression is notified to re-evaluate, and than cause **child.PreferredMinSize** to change.
|
||||
|
||||
**child.PreferredMinSize** causes **parent.Bounds** to re-evaluate because **MinSizeLimitation="LimitToElementAndChildren"**.
|
||||
When**parent.Bounds**is changed, the observed expression is notified to re-evaluate, and than cause**child.PreferredMinSize**to change.
|
||||
|
||||
Now parent grows bigger because **child.AlignmentToParent** is not **0** or **-1**, which causes **parent.Bounds** to change again.
|
||||
**child.PreferredMinSize**causes**parent.Bounds**to re-evaluate because**MinSizeLimitation="LimitToElementAndChildren"**.
|
||||
|
||||
The loop is infinite, and when it begins to happen (usually because of the window border is dragging to resize), **parent** will soon grows to super big and you are no longer able to properly operate against the window.
|
||||
Now parent grows bigger because**child.AlignmentToParent**is not**0**or**-1**, which causes**parent.Bounds**to change again.
|
||||
|
||||
The loop is infinite, and when it begins to happen (usually because of the window border is dragging to resize),**parent**will soon grows to super big and you are no longer able to properly operate against the window.
|
||||
|
||||
## Binding to ViewModel Properties
|
||||
|
||||
You could also bind something back to the view model by using **-set** property: ``` <Instance ref.Class="..."> <ref.Parameter Name="Something" Class="..."/> <Window ref.Name="self"> <att.Something-set X-bind="aControl.AProperty"/> <AControl ref.Name="aControl"/> </Window> </Instance> ``` **-set** here tells XML that, properties referenced in the tag **\<att.Something/\>** are in the object returning from the **Something** property of the window, which is the view model in **\<ref.Parameter/\>**. Now when **aControl.AProperty** is changed, the value will be updated to **Something.X** immediately.
|
||||
You could also bind something back to the view model by using**-set**property:
|
||||
```
|
||||
<Instance ref.Class="...">
|
||||
<ref.Parameter Name="Something" Class="..."/>
|
||||
<Window ref.Name="self">
|
||||
<att.Something-set X-bind="aControl.AProperty"/>
|
||||
<AControl ref.Name="aControl"/>
|
||||
</Window>
|
||||
</Instance>
|
||||
```
|
||||
**-set**here tells XML that, properties referenced in the tag**\<att.Something/\>**are in the object returning from the**Something**property of the window, which is the view model in**\<ref.Parameter/\>**. Now when**aControl.AProperty**is changed, the value will be updated to**Something.X**immediately.
|
||||
|
||||
## Bidirectional Binding
|
||||
|
||||
Bidirectional binding is a special type of binding, when two properties update each other.
|
||||
|
||||
[<CommonDatePickerLook/>](../.././gacui/components/ctemplates/commondatepickerlook.md) is a good example: ``` <Instance ref.CodeBehind="false" ref.Class="darkskin::DatePickerTemplate" ref.Styles="res://DarkSkin/Style"> <DatePickerTemplate ref.Name="self" Date-bind="look.Date" ...> <CommonDatePickerLook ref.Name="look" Date-bind="self.Date" .../> </DatePickerTemplate> </Instance> ``` In this example, when **self.Date** is changed, the value will be updates to **look.Date**, when **look.Date** is changed, the value will be updates to **self.Date**. Such biditional binding keep these two properties in sync, by using **-bind** twice on each other.
|
||||
[<CommonDatePickerLook/>](../.././gacui/components/ctemplates/commondatepickerlook.md)is a good example:
|
||||
```
|
||||
<Instance ref.CodeBehind="false" ref.Class="darkskin::DatePickerTemplate" ref.Styles="res://DarkSkin/Style">
|
||||
<DatePickerTemplate ref.Name="self" Date-bind="look.Date" ...>
|
||||
<CommonDatePickerLook ref.Name="look" Date-bind="self.Date" .../>
|
||||
</DatePickerTemplate>
|
||||
</Instance>
|
||||
```
|
||||
In this example, when**self.Date**is changed, the value will be updates to**look.Date**, when**look.Date**is changed, the value will be updates to**self.Date**. Such biditional binding keep these two properties in sync, by using**-bind**twice on each other.
|
||||
|
||||
This doesn't cause the update loop to run infinitely because these two **Date** properties don't trigger their property changing event if the updated value is the same to the value before updating.
|
||||
This doesn't cause the update loop to run infinitely because these two**Date**properties don't trigger their property changing event if the updated value is the same to the value before updating.
|
||||
|
||||
Properties create by the **prop Name : TYPE {}** syntax will not trigger the **NameChanged** event if the same value is updated to the property again. But for properties with explicit getter and setter, you must handle the setter properly: ``` class YourObject { var name: string = ""; event NameChanged(); func GetName(): string { return name; } func SetName(value: string): void { if (name != value) { name = value; NameChanged(); } } prop Name: string {GetName, SetName : NameChanged} } ``` Otherwise using bidirectional binding on this property will trigger an infinite loop.
|
||||
Properties create by the**prop Name : TYPE {}**syntax will not trigger the**NameChanged**event if the same value is updated to the property again. But for properties with explicit getter and setter, you must handle the setter properly:
|
||||
```
|
||||
class YourObject
|
||||
{
|
||||
var name: string = "";
|
||||
|
||||
event NameChanged();
|
||||
|
||||
func GetName(): string
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
func SetName(value: string): void
|
||||
{
|
||||
if (name != value)
|
||||
{
|
||||
name = value;
|
||||
NameChanged();
|
||||
}
|
||||
}
|
||||
|
||||
prop Name: string {GetName, SetName : NameChanged}
|
||||
}
|
||||
```
|
||||
Otherwise using bidirectional binding on this property will trigger an infinite loop.
|
||||
|
||||
|
||||
@@ -1,38 +1,67 @@
|
||||
# Cross XML Resource References
|
||||
|
||||
A GacUI XML Resource could [ use some resources in another XML ](../.././gacui/xmlres/cxrr.md). There are 3 types of resources: - Resource files: They could be accessed using **import-res://RESOURCE-NAME/...** in the **-uri binding**. - Objects that compiled to Workflow: They could be accessed using their generated class or interface names. - Everything else: They could not be accessed from another XML.
|
||||
A GacUI XML Resource could[use some resources in another XML](../.././gacui/xmlres/cxrr.md). There are 3 types of resources:
|
||||
- Resource files: They could be accessed using**import-res://RESOURCE-NAME/...**in the**-uri binding**.
|
||||
- Objects that compiled to Workflow: They could be accessed using their generated class or interface names.
|
||||
- Everything else: They could not be accessed from another XML.
|
||||
|
||||
## XML Resource Header
|
||||
|
||||
To make a GacUI XML Resource be able to depend on or be depended by another resource, a header is required in **GacGenConfig/Metadata** like this: ``` <Resource> <Folder name="GacGenConfig"> <Xml name="Metadata"> <ResourceMetadata Name="EditorRibbon" Version="1.0"> <Dependencies> <Resource Name="EditorBase"/> </Dependencies> </ResourceMetadata> </Xml> ... </Folder> ... </Resource> ``` - **/ResourceMetadata/@Name**: The name of the resource. All resources that loaded into an application should either have a unique name or have no name. If a resource want to depend on or to be depended by another resource, it should have a name. - **/ResourceMetadata/@Version**: The only legal value is **1.0**. It is bounded to the GacUI XML Resource Compiler (GacGen.exe). To ensure that all depended resources are compiled using a compatible version of compiler, an resource could only depend on another resource that has exactly the same version. - **/ResourceMetadata/Dependencies/Resource/@Name**: Here are all resources that the current resource depends on. The name must match their **/ResourceMetadata/@Name** in their metadata.
|
||||
To make a GacUI XML Resource be able to depend on or be depended by another resource, a header is required in**GacGenConfig/Metadata**like this:
|
||||
```
|
||||
<Resource>
|
||||
<Folder name="GacGenConfig">
|
||||
<Xml name="Metadata">
|
||||
<ResourceMetadata Name="EditorRibbon" Version="1.0">
|
||||
<Dependencies>
|
||||
<Resource Name="EditorBase"/>
|
||||
</Dependencies>
|
||||
</ResourceMetadata>
|
||||
</Xml>
|
||||
...
|
||||
</Folder>
|
||||
...
|
||||
</Resource>
|
||||
```
|
||||
|
||||
- **/ResourceMetadata/@Name**: The name of the resource. All resources that loaded into an application should either have a unique name or have no name. If a resource want to depend on or to be depended by another resource, it should have a name.
|
||||
- **/ResourceMetadata/@Version**: The only legal value is**1.0**. It is bounded to the GacUI XML Resource Compiler (GacGen.exe). To ensure that all depended resources are compiled using a compatible version of compiler, an resource could only depend on another resource that has exactly the same version.
|
||||
- **/ResourceMetadata/Dependencies/Resource/@Name**: Here are all resources that the current resource depends on. The name must match their**/ResourceMetadata/@Name**in their metadata.
|
||||
|
||||
## Compile Resource with Dependencies
|
||||
|
||||
[GacBuild.ps1](https://github.com/vczh-libraries/Release/tree/master/Tools) is the only tool to properly compile resources with dependencies.
|
||||
[GacBuild.ps1](https://github.com/vczh-libraries/Release/tree/master/Tools)is the only tool to properly compile resources with dependencies.
|
||||
|
||||
You need to have a file called **GacUI.xml**: ``` <GacUI/> ``` A GacUI XML Resource and all its dependeices must be put inside the folder containing **GacUI.xml**. Resource files could be put in any level of sub folders.
|
||||
You need to have a file called**GacUI.xml**:
|
||||
```
|
||||
<GacUI/>
|
||||
```
|
||||
A GacUI XML Resource and all its dependeices must be put inside the folder containing**GacUI.xml**. Resource files could be put in any level of sub folders.
|
||||
|
||||
Then you could call **GacBuild.ps1 -FileName path/to/GacUI.xml** in **PowerShell**. All resource files in the folder containing **GacUI.xml** will be found and compiled in the dependency order.
|
||||
Then you could call**GacBuild.ps1 -FileName path/to/GacUI.xml**in**PowerShell**. All resource files in the folder containing**GacUI.xml**will be found and compiled in the dependency order.
|
||||
|
||||
**GacBuild.ps1** forces incremental build. If a resource is not changed, and all its dependencies are not changed, then the resource will not be compiled again. You could use **GacClear.ps1 -FileName path/to/GacUI.xml** to clear all cache, the next time **GacBuild.ps1** will recompile every resource files.
|
||||
**GacBuild.ps1**forces incremental build. If a resource is not changed, and all its dependencies are not changed, then the resource will not be compiled again. You could use**GacClear.ps1 -FileName path/to/GacUI.xml**to clear all cache, the next time**GacBuild.ps1**will recompile every resource files.
|
||||
|
||||
Generated resource binaries, workflow binaries and C++ code will be put in places [ specified in each GacUI XML Resource ](../.././gacui/xmlres/cgc.md).
|
||||
Generated resource binaries, workflow binaries and C++ code will be put in places[specified in each GacUI XML Resource](../.././gacui/xmlres/cgc.md).
|
||||
|
||||
## Loading Resource Dependencies in your C++ Application
|
||||
|
||||
**vl::presentation::GetResourceManager()-\>LoadResourceOrPending(fileStream[, errors][, usage]);** is the only function to load compiled resource binaries: - **fileStream**: It could be any [vl::stream::IStream](../.././vlppos/using-streams.md), you could use **FileStream** here to load a resource from file. - **errors**: If the resource could not be loaded, errors will be stored in this list. An empty error list after calling this function means the resource is loaded properly. If the **errors** argument is not use, then the function will crash if there is any error. - **usage**: It could be **InstanceClass** if you include all Workflow binaries into this resource file, and **DataOnly** if not. A resource binary containing Workflow binaries could be produced using [res://GacGenCppConfig/ResX86/Resource and res://GacGenCppConfig/ResX/Resource](../.././gacui/xmlres/cgc.md)**The content of Workflow binaries is different for x86 or x64**, you need to load the correct one. Typically, if you use compiled resource with generated C++ files instead of Workflow binaries, you only need the first argument.
|
||||
**vl::presentation::GetResourceManager()-\>LoadResourceOrPending(fileStream[, errors][, usage]);**is the only function to load compiled resource binaries:
|
||||
- **fileStream**: It could be any[vl::stream::IStream](../.././vlppos/using-streams.md), you could use**FileStream**here to load a resource from file.
|
||||
- **errors**: If the resource could not be loaded, errors will be stored in this list. An empty error list after calling this function means the resource is loaded properly. If the**errors**argument is not use, then the function will crash if there is any error.
|
||||
- **usage**: It could be**InstanceClass**if you include all Workflow binaries into this resource file, and**DataOnly**if not. A resource binary containing Workflow binaries could be produced using[res://GacGenCppConfig/ResX86/Resource and res://GacGenCppConfig/ResX/Resource](../.././gacui/xmlres/cgc.md)**The content of Workflow binaries is different for x86 or x64**, you need to load the correct one.Typically, if you use compiled resource with generated C++ files instead of Workflow binaries, you only need the first argument.
|
||||
|
||||
You don't need to worry about the order to load resource files, they will be taken care of in this function, just call **LoadResourceOrPending** for all of them.
|
||||
You don't need to worry about the order to load resource files, they will be taken care of in this function, just call**LoadResourceOrPending**for all of them.
|
||||
|
||||
Calling **LoadResourceOrPending** without all depended resources prepared results in delay loading. Such resource will be automatically loaded after all depended resources are loaded. You could call **GetResource** to see if a resource has already been loaded or not. If it returns **null** but **LoadResourceOrPending** succeeded, it means some depended resources are not prepared yet, and the loading is delayed.
|
||||
Calling**LoadResourceOrPending**without all depended resources prepared results in delay loading. Such resource will be automatically loaded after all depended resources are loaded. You could call**GetResource**to see if a resource has already been loaded or not. If it returns**null**but**LoadResourceOrPending**succeeded, it means some depended resources are not prepared yet, and the loading is delayed.
|
||||
|
||||
## Get Rid of Resource Files
|
||||
|
||||
By using [CppResource or CppCompressed](../.././gacui/xmlres/cgc.md) in **res://GacGenConfig/Cpp**, you will get multiple cpp files for each GacUI XML Resource. Link all these cpp files to your project, resource binaries will be compiled into your executable file. When your application starts, all resources will be properly loaded before **GuiMain**.
|
||||
By using[CppResource or CppCompressed](../.././gacui/xmlres/cgc.md)in**res://GacGenConfig/Cpp**, you will get multiple cpp files for each GacUI XML Resource. Link all these cpp files to your project, resource binaries will be compiled into your executable file. When your application starts, all resources will be properly loaded before**GuiMain**.
|
||||
|
||||
## Using Resource in Dependedcies
|
||||
|
||||
If there is a resource object **res://path/to/the/resource** in a GacUI XML Resource called **BaseResource**, another GacUI XML Resource depending on it could use **import-res://BaseResource/path/to/the/resource**. Such resource path could be use in **-uri binding**, or in the **ResolveResource** method in all [root UI instance](../.././gacui/xmlres/instance/root_instance.md).
|
||||
If there is a resource object**res://path/to/the/resource**in a GacUI XML Resource called**BaseResource**, another GacUI XML Resource depending on it could use**import-res://BaseResource/path/to/the/resource**. Such resource path could be use in**-uri binding**, or in the**ResolveResource**method in all[root UI instance](../.././gacui/xmlres/instance/root_instance.md).
|
||||
|
||||
If a resource is compiled to Workflow classes or instances, just use the class or interface names directly. But if the resource is not in the dependency list (**/ResourceMetadata/Dependencies/Resource/@Name**), the class or interface name will not be found when running **GacBuild.ps1**, errors will be generated and the resource cannot be compiled.
|
||||
If a resource is compiled to Workflow classes or instances, just use the class or interface names directly. But if the resource is not in the dependency list (**/ResourceMetadata/Dependencies/Resource/@Name**), the class or interface name will not be found when running**GacBuild.ps1**, errors will be generated and the resource cannot be compiled.
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,28 +1,57 @@
|
||||
# Localization
|
||||
|
||||
The GacUI XML [<LocalizedStrings/>](../.././gacui/xmlres/tag_localizedstrings.md) resource creates multi-language string template as bindable objects.
|
||||
The GacUI XML[<LocalizedStrings/>](../.././gacui/xmlres/tag_localizedstrings.md)resource creates multi-language string template as bindable objects.
|
||||
|
||||
The GacUI XML [<LocalizedStringsInjection/>](../.././gacui/xmlres/tag_localizedstringsinjection.md) resource adds more languages to an existing **\<LocalizedStrings/\>**.
|
||||
The GacUI XML[<LocalizedStringsInjection/>](../.././gacui/xmlres/tag_localizedstringsinjection.md)resource adds more languages to an existing**\<LocalizedStrings/\>**.
|
||||
|
||||
## \<ref.LocalizedStrings/\>
|
||||
|
||||
**\<ref.LocalizedStrings/\>** imports a **\<LocalizedStrings/\>** to the current UI instance: ``` <ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/> ``` - **Name**: The name of this string resource. It will also create a property in the current UI instance in the same name. The property value could be changed at runtime. Unlike **\<ref.Parameter/\>**, the instance knows how to initialize a string resource, so it doesn't create a constructor parameter. - **Class**: The full name of the string resource class. The resource should look like this to be referenced using **Class="demo::StringResource"**: ``` <LocalizedStrings ref.Class="demo::StringResource" DefaultLocale="en-US"> ... </LocalizedStrings> ``` - **Default**: Specify a default string resource. If there are multiple **\<LocalizedStrings/\>**, only one of them could be the default string resource.
|
||||
**\<ref.LocalizedStrings/\>**imports a**\<LocalizedStrings/\>**to the current UI instance:
|
||||
```
|
||||
<ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/>
|
||||
```
|
||||
|
||||
- **Name**: The name of this string resource. It will also create a property in the current UI instance in the same name. The property value could be changed at runtime. Unlike**\<ref.Parameter/\>**, the instance knows how to initialize a string resource, so it doesn't create a constructor parameter.
|
||||
- **Class**: The full name of the string resource class. The resource should look like this to be referenced using**Class="demo::StringResource"**:
|
||||
```
|
||||
<LocalizedStrings ref.Class="demo::StringResource" DefaultLocale="en-US">
|
||||
...
|
||||
</LocalizedStrings>
|
||||
```
|
||||
|
||||
- **Default**: Specify a default string resource. If there are multiple**\<LocalizedStrings/\>**, only one of them could be the default string resource.
|
||||
|
||||
## -str Binding
|
||||
|
||||
The value of the **-str** binding must be a [ Workflow call expression ](../.././workflow/lang/expr.md). The function could be either **METHOD** or **NAME.METHOD**. - **METHOD**: This syntax use the **default string resource**. **METHOD** must be one of the **Name** attribute of a **\<String/\>** in the referenced **\<LocalizedStrings/\>**. - **NAME.METHOD**: Unlike the above one, this syntax use the **\<ref.LocalizedStrings/\>** whose **Name** attribute is **NAME**. Once the string resource and the string item is located, the **-str** binding will check if arguments match the type requirement. Note that parameter types of the same string item in different languages should be exactly the same in one **\<LocalizedStrings/\>**, so it doesn't matter which is the current UI language. This also ensure that you are able to switch the UI language at runtime.
|
||||
The value of the**-str**binding must be a[Workflow call expression](../.././workflow/lang/expr.md). The function could be either**METHOD**or**NAME.METHOD**.
|
||||
- **METHOD**: This syntax use the**default string resource**.**METHOD**must be one of the**Name**attribute of a**\<String/\>**in the referenced**\<LocalizedStrings/\>**.
|
||||
- **NAME.METHOD**: Unlike the above one, this syntax use the**\<ref.LocalizedStrings/\>**whose**Name**attribute is**NAME**.Once the string resource and the string item is located, the**-str**binding will check if arguments match the type requirement. Note that parameter types of the same string item in different languages should be exactly the same in one**\<LocalizedStrings/\>**, so it doesn't matter which is the current UI language. This also ensure that you are able to switch the UI language at runtime.
|
||||
|
||||
## Using -bind or -format on String Resources
|
||||
|
||||
For a string resource imported by: ``` <ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/> ``` The **-str** binding is also a data binding, so it knows when the **Strings** property is changed, and update the property value.
|
||||
For a string resource imported by:
|
||||
```
|
||||
<ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/>
|
||||
```
|
||||
The**-str**binding is also a data binding, so it knows when the**Strings**property is changed, and update the property value.
|
||||
|
||||
Assume the default string resource is **Strings**, the following binding code - **-str="Something(p1, p2, p3)"** - **-str="Strings.Something(p1, p2, p3)"** is equivalent to - **-bind="self.Strings.Something(p1, p2, p3)"** - **-format="$(self.Strings.Something(p1, p2, p3))"** when the current UI instance has a **ref.Name="self"** attribute.
|
||||
Assume the default string resource is**Strings**, the following binding code
|
||||
- **-str="Something(p1, p2, p3)"**
|
||||
- **-str="Strings.Something(p1, p2, p3)"**is equivalent to
|
||||
- **-bind="self.Strings.Something(p1, p2, p3)"**
|
||||
- **-format="$(self.Strings.Something(p1, p2, p3))"**when the current UI instance has a**ref.Name="self"**attribute.
|
||||
|
||||
## Switching the UI Language
|
||||
|
||||
The only way to specify the UI language is: - **C++**: GetApplication()-\>SetLocale(LOCALE); - **Workflow**: presentation::controls::GuiApplication.GetApplication().Locale = LOCALE; This configuration affect all windows in the current process.
|
||||
The only way to specify the UI language is:
|
||||
- **C++**: GetApplication()-\>SetLocale(LOCALE);
|
||||
- **Workflow**: presentation::controls::GuiApplication.GetApplication().Locale = LOCALE;This configuration affect all windows in the current process.
|
||||
|
||||
For a string resource imported by: ``` <ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/> ``` When the application locale is changed, the **Strings** property of the current UI object will be replaced by a new object, which is from a **\<Strings/\>** in the referenced **\<LocalizedStrings/\>** for that locale. If the specified locale doesn't exist in that localized string, the default one will be used.
|
||||
For a string resource imported by:
|
||||
```
|
||||
<ref.LocalizedStrings Name="Strings" Class="demo::StringResource" Default="true"/>
|
||||
```
|
||||
When the application locale is changed, the**Strings**property of the current UI object will be replaced by a new object, which is from a**\<Strings/\>**in the referenced**\<LocalizedStrings/\>**for that locale. If the specified locale doesn't exist in that localized string, the default one will be used.
|
||||
|
||||
Such **\<LocalizedStrings/\>** will also create an interface called demo::**I**StringResource**Strings**, which becomes the type of the **Strings** property if it is imported using the above **\<ref.LocalizedStrings/\>**. Usually you don't need to use either the generated class **demo::StringResource**. or the generated interface **demo::IStringResourceStrings**.
|
||||
Such**\<LocalizedStrings/\>**will also create an interface called demo::**I**StringResource**Strings**, which becomes the type of the**Strings**property if it is imported using the above**\<ref.LocalizedStrings/\>**. Usually you don't need to use either the generated class**demo::StringResource**. or the generated interface**demo::IStringResourceStrings**.
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# TAB and Control Focus
|
||||
|
||||
If a focusable control is put on a window, by setting the [TabPriority](../.././gacui/components/controls/basic/home.md) property to a value that is not **-1**, then it could get focused by pressing **TAB**.
|
||||
If a focusable control is put on a window, by setting the[TabPriority](../.././gacui/components/controls/basic/home.md)property to a value that is not**-1**, then it could get focused by pressing**TAB**.
|
||||
|
||||
Pressing **TAB** switches the focus between different controls in a window, in the order of their **TabPriority** from less to greater, when both **IsTabEnabled** and **IsTabAvailable** return **true**. If the value is less than **-1**, then they will be treated as **0xFFFFFFFFFFFFFFFF**. The order between controls with the same **TabPriority** is undefined.
|
||||
Pressing**TAB**switches the focus between different controls in a window, in the order of their**TabPriority**from less to greater, when both**IsTabEnabled**and**IsTabAvailable**return**true**. If the value is less than**-1**, then they will be treated as**0xFFFFFFFFFFFFFFFF**. The order between controls with the same**TabPriority**is undefined.
|
||||
|
||||
## Behavior after being Focused
|
||||
|
||||
A focusable control will just get focused if **TAB** decides to give the focus to this control.
|
||||
A focusable control will just get focused if**TAB**decides to give the focus to this control.
|
||||
|
||||
## Create your own Behavior
|
||||
|
||||
If a new control class is created, there are multiple ways to customize the behavior about how a control should react to **TAB**:
|
||||
If a new control class is created, there are multiple ways to customize the behavior about how a control should react to**TAB**:
|
||||
|
||||
### Using IGuiTabAction
|
||||
|
||||
**IGuiTabAction** is a protected base class of all controls. If a new control is created, methods could be overriden.
|
||||
**IGuiTabAction**is a protected base class of all controls. If a new control is created, methods could be overriden.
|
||||
|
||||
**IsTabEnabled** returns **true** if the control is visible and enabled. **IsTabAvailable** returns **true** if the control is focusable.
|
||||
**IsTabEnabled**returns**true**if the control is visible and enabled.**IsTabAvailable**returns**true**if the control is focusable.
|
||||
|
||||
The default value from **GetAcceptTabInput** is **false**. But a few controls like text controls or document controls set this value to **true**. When **GetAcceptTabInput** is **true**, it means this control defines the behavior for this key, like entering a **TAB** character, so that it doesn't want the focus to be switched to another control. Calling **SetAcceptTabInput** could change this value.
|
||||
The default value from**GetAcceptTabInput**is**false**. But a few controls like text controls or document controls set this value to**true**. When**GetAcceptTabInput**is**true**, it means this control defines the behavior for this key, like entering a**TAB**character, so that it doesn't want the focus to be switched to another control. Calling**SetAcceptTabInput**could change this value.
|
||||
|
||||
|
||||
@@ -1,30 +1,132 @@
|
||||
# Interop with C++ View Model
|
||||
|
||||
It is recommended to use the [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) pattern with GacUI: - `empty list item` **Model**: It refers to a domain model. Code in **Model** solves real problem that users need. It could be an object-oriented design of a domain, it could also be a data access layer to the data in database, from the internet, or any possible way. - `empty list item` **ViewModel**: It refers to a set of interface exposing the **Model** in a convient way for **Views**. Data organization in **Model** doesn't have to be UI friendly. It is the **ViewModel** who exposes a right set of operations, to make **Views** access **Model** convenient. For example, there are many applications offer list sorting to users. Data in **Model** is not sorted, it could be indexed, because there is so many way to sort the data, it is a waste of storage to cache all sorting result. When a user sort the data in a specific way, it is the **ViewModel** who handels the sorting. the **ViewModel** accesses the data, return the data organization in a sorted way. - `empty list item` **View**: A **View** could be the actual UI of an application, it could also be a set of unit tests. **Views** access **ViewModel**, typically it doesn't access **Model**.
|
||||
It is recommended to use the[MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel)pattern with GacUI:
|
||||
- `empty list item`
|
||||
**Model**: It refers to a domain model. Code in**Model**solves real problem that users need. It could be an object-oriented design of a domain, it could also be a data access layer to the data in database, from the internet, or any possible way.
|
||||
- `empty list item`
|
||||
**ViewModel**: It refers to a set of interface exposing the**Model**in a convient way for**Views**. Data organization in**Model**doesn't have to be UI friendly. It is the**ViewModel**who exposes a right set of operations, to make**Views**access**Model**convenient.
|
||||
For example, there are many applications offer list sorting to users. Data in**Model**is not sorted, it could be indexed, because there is so many way to sort the data, it is a waste of storage to cache all sorting result. When a user sort the data in a specific way, it is the**ViewModel**who handels the sorting. the**ViewModel**accesses the data, return the data organization in a sorted way.
|
||||
- `empty list item`
|
||||
**View**: A**View**could be the actual UI of an application, it could also be a set of unit tests.**Views**access**ViewModel**, typically it doesn't access**Model**.
|
||||
|
||||
In GacUI, **ViewModels** are defined as a set of interfaces in [Workflow script files](../.././gacui/xmlres/tag_script.md). **Views** are defined as a set of [windows and controls](../.././gacui/xmlres/instance/root_instance.md).
|
||||
In GacUI,**ViewModels**are defined as a set of interfaces in[Workflow script files](../.././gacui/xmlres/tag_script.md).**Views**are defined as a set of[windows and controls](../.././gacui/xmlres/instance/root_instance.md).
|
||||
|
||||
All **ViewModels** that are needed in a **View** are defined as [<ref.Parameter/>](../.././gacui/xmlres/tag_instance.md), which represents constructor arguments to that **View**. The **Class** attributes of such **\<ref.Parameter/\>** will be interfaces for **ViewModels**.
|
||||
All**ViewModels**that are needed in a**View**are defined as[<ref.Parameter/>](../.././gacui/xmlres/tag_instance.md), which represents constructor arguments to that**View**. The**Class**attributes of such**\<ref.Parameter/\>**will be interfaces for**ViewModels**.
|
||||
|
||||
In the GacUI entry point (the **GuiMain** function), a main window will be created. If the main window needs **ViewModels**, the main window **\<Instance/\>** will have one or more **\<ref.Parameter/\>**, then the constructor of the main window will have one or more constructor arguments.
|
||||
In the GacUI entry point (the**GuiMain**function), a main window will be created. If the main window needs**ViewModels**, the main window**\<Instance/\>**will have one or more**\<ref.Parameter/\>**, then the constructor of the main window will have one or more constructor arguments.
|
||||
|
||||
Now, **GuiMain** just needs to create classes that implement these interfaces, and gives all of them to the constructor of the main window, then **ViewModels** and the **View** is connected together.
|
||||
Now,**GuiMain**just needs to create classes that implement these interfaces, and gives all of them to the constructor of the main window, then**ViewModels**and the**View**is connected together.
|
||||
|
||||
## Sample
|
||||
|
||||
[This](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_HelloWorlds/MVVM) is a very simple example for using MVVM in GacUI.
|
||||
[This](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_HelloWorlds/MVVM)is a very simple example for using MVVM in GacUI.
|
||||
|
||||

|
||||
|
||||
The **ViewModel** is an interface: ``` interface IViewModel { func GetUserName() : string; func SetUserName(value : string) : void; prop UserName : string {GetUserName, SetUserName} func GetPassword() : string; func SetPassword(value : string) : void; prop Password : string {GetPassword, SetPassword} func GetUserNameError() : string; event UserNameErrorChanged(); prop UserNameError : string {GetUserNameError : UserNameErrorChanged} func GetPasswordError() : string; event PasswordErrorChanged(); prop PasswordError : string {GetPasswordError : PasswordErrorChanged} func SignUp() : bool; } ``` It defines all **View** needs to know: - Accessing the user name and the password. - Retriving validation results for the user name and the password.
|
||||
The**ViewModel**is an interface:
|
||||
```
|
||||
interface IViewModel
|
||||
{
|
||||
func GetUserName() : string;
|
||||
func SetUserName(value : string) : void;
|
||||
prop UserName : string {GetUserName, SetUserName}
|
||||
|
||||
func GetPassword() : string;
|
||||
func SetPassword(value : string) : void;
|
||||
prop Password : string {GetPassword, SetPassword}
|
||||
|
||||
func GetUserNameError() : string;
|
||||
event UserNameErrorChanged();
|
||||
prop UserNameError : string {GetUserNameError : UserNameErrorChanged}
|
||||
|
||||
func GetPasswordError() : string;
|
||||
event PasswordErrorChanged();
|
||||
prop PasswordError : string {GetPasswordError : PasswordErrorChanged}
|
||||
|
||||
func SignUp() : bool;
|
||||
}
|
||||
```
|
||||
It defines all**View**needs to know:
|
||||
- Accessing the user name and the password.
|
||||
- Retriving validation results for the user name and the password.
|
||||
|
||||
When the content of a text box is changed, the data is stored to the view model. This is implemented using data bindings to the view model object: ``` <ref.Parameter Name="ViewModel" Class="vm::IViewModel"/> <Window ref.Name="self" Text="Let's Sign Up!" ClientSize="x:320 y:320"> <att.ViewModel-set UserName-bind="textBoxUserName.Text" Password-bind="textBoxPassword.Text"/> ... ```
|
||||
When the content of a text box is changed, the data is stored to the view model. This is implemented using data bindings to the view model object:
|
||||
```
|
||||
<ref.Parameter Name="ViewModel" Class="vm::IViewModel"/>
|
||||
<Window ref.Name="self" Text="Let's Sign Up!" ClientSize="x:320 y:320">
|
||||
<att.ViewModel-set UserName-bind="textBoxUserName.Text" Password-bind="textBoxPassword.Text"/>
|
||||
...
|
||||
```
|
||||
|
||||
When the validation result is changed, errors are displayed to the UI immediately. This is implemented using data bindings to UI objects: ``` <SolidLabel Text-bind="ViewModel.UserNameError"/> ```
|
||||
|
||||
When the user name or the password is stored to the view model, validation results are updated automatically. This is implemented in a C++ class which inherits the interface: ``` class ViewModel : public Object, public virtual vm::IViewModel { private: WString userName; WString password; Regex regexLcLetters; Regex regexUcLetters; Regex regexNumbers; public: ViewModel() :regexLcLetters(L"[a-z]") , regexUcLetters(L"[A-Z]") , regexNumbers(L"[0-9]") { } ... WString GetPassword()override { return password; } void SetPassword(const WString& value)override { password = value; PasswordErrorChanged(); } WString GetPasswordError()override { if (password == L"") { return L"Password should not be empty."; } bool containsLowerCases = regexLcLetters.Match(password); bool containsUpperCases = regexUcLetters.Match(password); bool containsNumbers = regexNumbers.Match(password); if (!containsLowerCases || !containsUpperCases || !containsNumbers) { return L"Password should contains at least one lower case letter, one upper case letter and one digit."; } return L""; } }; ```
|
||||
When the validation result is changed, errors are displayed to the UI immediately. This is implemented using data bindings to UI objects:
|
||||
```
|
||||
<SolidLabel Text-bind="ViewModel.UserNameError"/>
|
||||
```
|
||||
|
||||
It is very easy to connect the **ViewModel** to the **View**: ``` void GuiMain() { ... auto viewModel = Ptr(new ViewModel); auto window = new helloworld::MainWindow(viewModel); ... } ```
|
||||
|
||||
Collection objects or tree-like objects can be binded to [list controls](../.././gacui/components/controls/list/home.md) directly. Data bindings accept any [workflow expressions](../.././workflow/lang/bind.md) that compiles. MVVM in GacUI is very powerful, you are free to choose any way to define **ViewModel** interfaces, and it is always possible to bind it to the UI.
|
||||
When the user name or the password is stored to the view model, validation results are updated automatically. This is implemented in a C++ class which inherits the interface:
|
||||
```
|
||||
class ViewModel : public Object, public virtual vm::IViewModel
|
||||
{
|
||||
private:
|
||||
WString userName;
|
||||
WString password;
|
||||
Regex regexLcLetters;
|
||||
Regex regexUcLetters;
|
||||
Regex regexNumbers;
|
||||
|
||||
public:
|
||||
ViewModel()
|
||||
:regexLcLetters(L"[a-z]")
|
||||
, regexUcLetters(L"[A-Z]")
|
||||
, regexNumbers(L"[0-9]")
|
||||
{
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
WString GetPassword()override
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
void SetPassword(const WString& value)override
|
||||
{
|
||||
password = value;
|
||||
PasswordErrorChanged();
|
||||
}
|
||||
|
||||
WString GetPasswordError()override
|
||||
{
|
||||
if (password == L"")
|
||||
{
|
||||
return L"Password should not be empty.";
|
||||
}
|
||||
bool containsLowerCases = regexLcLetters.Match(password);
|
||||
bool containsUpperCases = regexUcLetters.Match(password);
|
||||
bool containsNumbers = regexNumbers.Match(password);
|
||||
if (!containsLowerCases || !containsUpperCases || !containsNumbers)
|
||||
{
|
||||
return L"Password should contains at least one lower case letter, one upper case letter and one digit.";
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
It is very easy to connect the**ViewModel**to the**View**:
|
||||
```
|
||||
void GuiMain()
|
||||
{
|
||||
...
|
||||
auto viewModel = Ptr(new ViewModel);
|
||||
auto window = new helloworld::MainWindow(viewModel);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Collection objects or tree-like objects can be binded to[list controls](../.././gacui/components/controls/list/home.md)directly. Data bindings accept any[workflow expressions](../.././workflow/lang/bind.md)that compiles. MVVM in GacUI is very powerful, you are free to choose any way to define**ViewModel**interfaces, and it is always possible to bind it to the UI.
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# \<ColorDialog\>
|
||||
|
||||
**\<ColorDialog/\>** displays a OS native color dialog.
|
||||
**\<ColorDialog/\>**displays a OS native color dialog.
|
||||
|
||||
## Input / Output Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to create a default user input. These properties will be changed after calling **ShowDialog** if the user change the default input.
|
||||
Set these properties before calling**ShowDialog**to create a default user input. These properties will be changed after calling**ShowDialog**if the user change the default input.
|
||||
|
||||
### SelectedColor
|
||||
|
||||
This property defines the selected color. If **ShowDialog** returns **false**, the value of this property is undefined.
|
||||
This property defines the selected color. If**ShowDialog**returns**false**, the value of this property is undefined.
|
||||
|
||||
## Input Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to define the content of the dialog.
|
||||
Set these properties before calling**ShowDialog**to define the content of the dialog.
|
||||
|
||||
### EnabledCustomColor
|
||||
|
||||
Set this property to **true** to enable an extended area, allowing the user to choose a color that is not in the predefined color list.
|
||||
Set this property to**true**to enable an extended area, allowing the user to choose a color that is not in the predefined color list.
|
||||
|
||||
### OpenedCustomColor
|
||||
|
||||
Set this property to **true** to display the custom color area by default. Otherwise the area is collapsed, but the user could still open it in the dialog.
|
||||
Set this property to**true**to display the custom color area by default. Otherwise the area is collapsed, but the user could still open it in the dialog.
|
||||
|
||||
## ShowDialog Method
|
||||
|
||||
Call this function to display a dialog, and return **true** if a color is selected.
|
||||
Call this function to display a dialog, and return**true**if a color is selected.
|
||||
|
||||
## Output Properties
|
||||
|
||||
Read these properties after calling **ShowDialog** for user input.
|
||||
Read these properties after calling**ShowDialog**for user input.
|
||||
|
||||
### CustomColors
|
||||
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
# \<FontDialog\>
|
||||
|
||||
**\<FontDialog/\>** displays a OS native font dialog.
|
||||
**\<FontDialog/\>**displays a OS native font dialog.
|
||||
|
||||
## Input / Output Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to create a default user input. These properties will be changed after calling **ShowDialog** if the user change the default input.
|
||||
Set these properties before calling**ShowDialog**to create a default user input. These properties will be changed after calling**ShowDialog**if the user change the default input.
|
||||
|
||||
### SelectedFont
|
||||
|
||||
This property defines the selected font. If **ShowDialog** returns **false**, the value of this property is undefined.
|
||||
This property defines the selected font. If**ShowDialog**returns**false**, the value of this property is undefined.
|
||||
|
||||
### SelectedColor
|
||||
|
||||
This property defines the selected color. If **ShowDialog** returns **false**, the value of this property is undefined.
|
||||
This property defines the selected color. If**ShowDialog**returns**false**, the value of this property is undefined.
|
||||
|
||||
## Input Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to define the content of the dialog.
|
||||
Set these properties before calling**ShowDialog**to define the content of the dialog.
|
||||
|
||||
### ShowSelection
|
||||
|
||||
Set this property to **true** to highlight the **SelectedFont** and **SelectedColor**.
|
||||
Set this property to**true**to highlight the**SelectedFont**and**SelectedColor**.
|
||||
|
||||
### ShowEffect
|
||||
|
||||
Set this property to **true** to enable the font review area.
|
||||
Set this property to**true**to enable the font review area.
|
||||
|
||||
### ForceFontExist
|
||||
|
||||
Set this property to **true** to ensure user cannot select an unexisting font.
|
||||
Set this property to**true**to ensure user cannot select an unexisting font.
|
||||
|
||||
## ShowDialog Method
|
||||
|
||||
Call this function to display a dialog, and return **true** if a font is selected.
|
||||
Call this function to display a dialog, and return**true**if a font is selected.
|
||||
|
||||
|
||||
@@ -2,5 +2,13 @@
|
||||
|
||||
Components offer other features that are not involved in rendering.
|
||||
|
||||
Here are all predefined components in GacUI: - [GuiSelectableButton::MutexGroupController](../../.././gacui/components/controls/basic/selectableButton.md) - [<ToolstripCommand/>](../../.././gacui/components/controls/toolstrip/toolstripbutton.md) - **GuiDialogBase** - [<MessageDialog/>](../../.././gacui/components/components/messagedialog.md) - [<ColorDialog/>](../../.././gacui/components/components/colordialog.md) - [<FontDialog/>](../../.././gacui/components/components/fontdialog.md) - [<OpenFileDialog/>](../../.././gacui/components/components/openfiledialog.md) - [<SaveFileDialog/>](../../.././gacui/components/components/savefiledialog.md)
|
||||
Here are all predefined components in GacUI:
|
||||
- [GuiSelectableButton::MutexGroupController](../../.././gacui/components/controls/basic/selectableButton.md)
|
||||
- [<ToolstripCommand/>](../../.././gacui/components/controls/toolstrip/toolstripbutton.md)
|
||||
- **GuiDialogBase**
|
||||
- [<MessageDialog/>](../../.././gacui/components/components/messagedialog.md)
|
||||
- [<ColorDialog/>](../../.././gacui/components/components/colordialog.md)
|
||||
- [<FontDialog/>](../../.././gacui/components/components/fontdialog.md)
|
||||
- [<OpenFileDialog/>](../../.././gacui/components/components/openfiledialog.md)
|
||||
- [<SaveFileDialog/>](../../.././gacui/components/components/savefiledialog.md)
|
||||
|
||||
|
||||
@@ -1,26 +1,44 @@
|
||||
# \<MessageDialog\>
|
||||
|
||||
**\<MessageDialog/\>** displays a OS native message dialog.
|
||||
**\<MessageDialog/\>**displays a OS native message dialog.
|
||||
|
||||
## Input Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to define the content of the dialog.
|
||||
Set these properties before calling**ShowDialog**to define the content of the dialog.
|
||||
|
||||
### Input
|
||||
|
||||
The value of this property must be one of the followuing values: - **DisplayOK**: Display OK button. - **DisplayOKCancel**: Display OK / Cancel button. - **DisplayYesNo**: Display Yes / No button. - **DisplayYesNoCancel**: Display Yes / No / Cancel button. - **DisplayRetryCancel**: Display Retry / Cancel button. - **DisplayAbortRetryIgnore**: Display Abort / Retry / Ignore button. - **DisplayCancelTryAgainContinue**: Display Cancel / Try Again / Continue button.
|
||||
The value of this property must be one of the followuing values:
|
||||
- **DisplayOK**: Display OK button.
|
||||
- **DisplayOKCancel**: Display OK / Cancel button.
|
||||
- **DisplayYesNo**: Display Yes / No button.
|
||||
- **DisplayYesNoCancel**: Display Yes / No / Cancel button.
|
||||
- **DisplayRetryCancel**: Display Retry / Cancel button.
|
||||
- **DisplayAbortRetryIgnore**: Display Abort / Retry / Ignore button.
|
||||
- **DisplayCancelTryAgainContinue**: Display Cancel / Try Again / Continue button.
|
||||
|
||||
### DefaultButton
|
||||
|
||||
The value of this property must be one of the followuing values: - **DefaultFirst**: The first button is focused right after the dialog is displayed. - **DefaultSecond**: The second button is focused right after the dialog is displayed. - **DefaultThird**: The third button is focused right after the dialog is displayed.
|
||||
The value of this property must be one of the followuing values:
|
||||
- **DefaultFirst**: The first button is focused right after the dialog is displayed.
|
||||
- **DefaultSecond**: The second button is focused right after the dialog is displayed.
|
||||
- **DefaultThird**: The third button is focused right after the dialog is displayed.
|
||||
|
||||
### Icon
|
||||
|
||||
The value of this property must be one of the followuing values: - **IconNone**: Do not display an icon. - **IconError**: Display an error icon. - **IconQuestion**: Display a question icon. - **IconWarning**: Display a warning icon. - **IconInformation**: Display an information icon.
|
||||
The value of this property must be one of the followuing values:
|
||||
- **IconNone**: Do not display an icon.
|
||||
- **IconError**: Display an error icon.
|
||||
- **IconQuestion**: Display a question icon.
|
||||
- **IconWarning**: Display a warning icon.
|
||||
- **IconInformation**: Display an information icon.
|
||||
|
||||
### ModalOption
|
||||
|
||||
The value of this property must be one of the followuing values: - **ModalWindow**: The current window is disabled until the dialog is closed. - **ModalTask**: All window of the current application is disabled until the dialog is closed. - **ModalSystem**: Same as **ModelTask** and the dialog is set to top-most.
|
||||
The value of this property must be one of the followuing values:
|
||||
- **ModalWindow**: The current window is disabled until the dialog is closed.
|
||||
- **ModalTask**: All window of the current application is disabled until the dialog is closed.
|
||||
- **ModalSystem**: Same as**ModelTask**and the dialog is set to top-most.
|
||||
|
||||
### Text
|
||||
|
||||
@@ -32,5 +50,14 @@ This property defines the title of the dialog.
|
||||
|
||||
## ShowDialog Method
|
||||
|
||||
Call this function to display a dialog, and returns the button that is clicked to close the dialog: - **SelectOK**: The OK button is clicked. - **SelectCancel**: The Cancel button is clicked. - **SelectYes**: The Yes button is clicked. - **SelectNo**: The No button is clicked. - **SelectRetry**: The Retry button is clicked. - **SelectAbort**: The Abort button is clicked. - **SelectIgnore**: The Ignore button is clicked. - **SelectTryAgain**: The Try Again button is clicked. - **SelectContinue**: The Continue button is clicked.
|
||||
Call this function to display a dialog, and returns the button that is clicked to close the dialog:
|
||||
- **SelectOK**: The OK button is clicked.
|
||||
- **SelectCancel**: The Cancel button is clicked.
|
||||
- **SelectYes**: The Yes button is clicked.
|
||||
- **SelectNo**: The No button is clicked.
|
||||
- **SelectRetry**: The Retry button is clicked.
|
||||
- **SelectAbort**: The Abort button is clicked.
|
||||
- **SelectIgnore**: The Ignore button is clicked.
|
||||
- **SelectTryAgain**: The Try Again button is clicked.
|
||||
- **SelectContinue**: The Continue button is clicked.
|
||||
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
# \<OpenFileDialog\>
|
||||
|
||||
**\<OpenFileDialog/\>** displays a OS native open file dialog.
|
||||
**\<OpenFileDialog/\>**displays a OS native open file dialog.
|
||||
|
||||
## Input / Output Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to create a default user input. These properties will be changed after calling **ShowDialog** if the user change the default input.
|
||||
Set these properties before calling**ShowDialog**to create a default user input. These properties will be changed after calling**ShowDialog**if the user change the default input.
|
||||
|
||||
### FileName
|
||||
|
||||
This property defines the full path of the selected file. If **ShowDialog** returns **false**, the value of this property is undefined.
|
||||
This property defines the full path of the selected file. If**ShowDialog**returns**false**, the value of this property is undefined.
|
||||
|
||||
## Input Properties
|
||||
|
||||
Set these properties before calling **ShowDialog** to define the content of the dialog.
|
||||
Set these properties before calling**ShowDialog**to define the content of the dialog.
|
||||
|
||||
### Filter
|
||||
|
||||
This property defines a file filter by wildcard.
|
||||
|
||||
Pattern names and wildcards in a filter are splitted by "|". For example, a filter to display text files or all files will typically be: ``` Text Files (*.txt)|*.txt|All Files (*.*)|*.* ``` This filter defines two filters: - **Text Files (*.txt)**: its wildcard is *.txt - **All Files (*.*)**: its wildcard is *.*
|
||||
Pattern names and wildcards in a filter are splitted by "|". For example, a filter to display text files or all files will typically be:
|
||||
```
|
||||
Text Files (*.txt)|*.txt|All Files (*.*)|*.*
|
||||
```
|
||||
This filter defines two filters:
|
||||
- **Text Files (*.txt)**: its wildcard is *.txt
|
||||
- **All Files (*.*)**: its wildcard is *.*
|
||||
|
||||
### FilterIndex
|
||||
|
||||
This property defines the default selected filter, starting from **0**.
|
||||
This property defines the default selected filter, starting from**0**.
|
||||
|
||||
### EnabledPreview
|
||||
|
||||
Set this property to **true** to enable the preview area. When a file is selected, its content will be displayed in the preview area.
|
||||
Set this property to**true**to enable the preview area. When a file is selected, its content will be displayed in the preview area.
|
||||
|
||||
### Title
|
||||
|
||||
@@ -40,23 +46,32 @@ This property defines the default folder of the dialog.
|
||||
|
||||
This property defines the default extension of the dialog.
|
||||
|
||||
If a file is selected by manually entering a file name, the **DefaultExtension** will be appended after the file name if the file extension is not entered.
|
||||
If a file is selected by manually entering a file name, the**DefaultExtension**will be appended after the file name if the file extension is not entered.
|
||||
|
||||
**IMPORTANT**: The value of the **DefaultExtension** property does not include the "." character. For example, an extension for text files is **txt**, instead of **.txt**.
|
||||
**IMPORTANT**: The value of the**DefaultExtension**property does not include the "." character. For example, an extension for text files is**txt**, instead of**.txt**.
|
||||
|
||||
### Options
|
||||
|
||||
The value of this property must be one of the following values, or multiple values combined together: - **FileDialogAllowMultipleSelection**: Allow multiple selection. - **FileDialogFileMustExist**: Prevent the user to select unexisting files. - **FileDialogShowReadOnlyCheckBox**: Show the "Read Only" check box. - **FileDialogDereferenceLinks**: Dereference link files. **FileName** and **FileNames** will contain the full path of actual files. - **FileDialogShowNetworkButton**: Show the "Network" button to allow selection of objects across the network. - **FileDialogPromptCreateFile**: Prompt if a new file is going to be created. - **FileDialogPromptOverwriteFile**: Promt if a existing file is going to be overwritten. - **FileDialogDirectoryMustExist**: Prevent the user to select an unexisting directory. - **FileDialogAddToRecent**: Add user selected files to "Recent" directory.
|
||||
The value of this property must be one of the following values, or multiple values combined together:
|
||||
- **FileDialogAllowMultipleSelection**: Allow multiple selection.
|
||||
- **FileDialogFileMustExist**: Prevent the user to select unexisting files.
|
||||
- **FileDialogShowReadOnlyCheckBox**: Show the "Read Only" check box.
|
||||
- **FileDialogDereferenceLinks**: Dereference link files.**FileName**and**FileNames**will contain the full path of actual files.
|
||||
- **FileDialogShowNetworkButton**: Show the "Network" button to allow selection of objects across the network.
|
||||
- **FileDialogPromptCreateFile**: Prompt if a new file is going to be created.
|
||||
- **FileDialogPromptOverwriteFile**: Promt if a existing file is going to be overwritten.
|
||||
- **FileDialogDirectoryMustExist**: Prevent the user to select an unexisting directory.
|
||||
- **FileDialogAddToRecent**: Add user selected files to "Recent" directory.
|
||||
|
||||
## ShowDialog Method
|
||||
|
||||
Call this function to display a dialog, and return **true** if a file is selected.
|
||||
Call this function to display a dialog, and return**true**if a file is selected.
|
||||
|
||||
## Output Properties
|
||||
|
||||
Read these properties after calling **ShowDialog** for user input.
|
||||
Read these properties after calling**ShowDialog**for user input.
|
||||
|
||||
### FileNames
|
||||
|
||||
This property returns full paths of all selected files. If **ShowDialog** returns **false**, the value of this property is undefined.
|
||||
This property returns full paths of all selected files. If**ShowDialog**returns**false**, the value of this property is undefined.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# \<SaveFileDialog\>
|
||||
|
||||
**\<SaveFileDialog/\>** displays a OS native save file dialog.
|
||||
**\<SaveFileDialog/\>**displays a OS native save file dialog.
|
||||
|
||||
**\<SaveFileDialog/\>** shares all properties and methods with [<OpenFileDialog/>](../../.././gacui/components/components/openfiledialog.md), except that the **FileNames** property does not exist in **\<SaveFileDialog/\>**.
|
||||
**\<SaveFileDialog/\>**shares all properties and methods with[<OpenFileDialog/>](../../.././gacui/components/components/openfiledialog.md), except that the**FileNames**property does not exist in**\<SaveFileDialog/\>**.
|
||||
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
# \<Bounds\>
|
||||
|
||||
**\<Bounds/\>** is able to set a relative position directly. But usually this composition is used when you just need to have a composition.
|
||||
**\<Bounds/\>**is able to set a relative position directly. But usually this composition is used when you just need to have a composition.
|
||||
|
||||
Three properties are provided by **\<Bounds/\>**:
|
||||
Three properties are provided by**\<Bounds/\>**:
|
||||
|
||||
## ExpectedBounds
|
||||
|
||||
To set a relative position, the default value is 0 for all its components.
|
||||
|
||||
**IMPORTANT**: The relative position of a composition does not always listen to the value of **ExpectedBounds**.
|
||||
**IMPORTANT**: The relative position of a composition does not always listen to the value of**ExpectedBounds**.
|
||||
|
||||
**ExpectedBounds** is only a suggestion. If any component of **AlignmentToParent** is not **-1**, the result will be affected accordingly.
|
||||
**ExpectedBounds**is only a suggestion. If any component of**AlignmentToParent**is not**-1**, the result will be affected accordingly.
|
||||
|
||||
The size of **ExpectedBounds** limits the composition's minimum size.
|
||||
The size of**ExpectedBounds**limits the composition's minimum size.
|
||||
|
||||
Please check out [this page](../../.././gacui/components/compositions/home.md) for more information.
|
||||
Please check out[this page](../../.././gacui/components/compositions/home.md)for more information.
|
||||
|
||||
## AlignmentToParent
|
||||
|
||||
**AlignmentToParent** is added for all compositions that can control the relative position by themselves. The position of **\<StackItem/\>** and **\<FlowItem/\>** are completely decided by **\<Stack/\>** and **\<Flow/\>**, **AlignmentToParent** does not exist in these compositions.
|
||||
**AlignmentToParent**is added for all compositions that can control the relative position by themselves. The position of**\<StackItem/\>**and**\<FlowItem/\>**are completely decided by**\<Stack/\>**and**\<Flow/\>**,**AlignmentToParent**does not exist in these compositions.
|
||||
|
||||
Please check out [this page](../../.././gacui/components/compositions/home.md) for more information.
|
||||
Please check out[this page](../../.././gacui/components/compositions/home.md)for more information.
|
||||
|
||||
## Sample
|
||||
|
||||
- Source code: [layout_bounds](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/layout_bounds/Resource.xml) - 
|
||||
|
||||
- Source code:[layout_bounds](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/layout_bounds/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,112 +1,171 @@
|
||||
# Handling Input Events
|
||||
|
||||
Raw input events are in compositions. Normally a composition doesn't receive events, until **GuiGraphicsComposition**::**GetEventReceiver** is called. This function create a big object containing all event registrations inside it, and cause **GuiGraphicsComposition**::**HasEventReceiver** to become **true** forever. You are not able to free the space of event registration object once it is associated to a composition.
|
||||
Raw input events are in compositions. Normally a composition doesn't receive events, until**GuiGraphicsComposition**::**GetEventReceiver**is called. This function create a big object containing all event registrations inside it, and cause**GuiGraphicsComposition**::**HasEventReceiver**to become**true**forever. You are not able to free the space of event registration object once it is associated to a composition.
|
||||
|
||||
In the event registration object you will find a lot of fields for events, for example, **leftButtonDown**. There are 3 methods for subscribing an event: - composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachMethod**: subscribe an event using an object and a member function pointer. - composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachFunction**: subscribe an event using a function pointer or a **vl::Func\<...\>** functor. - composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachLambda**: subscribe an event using a lambda expression or other functors. All 3 methods returns a new handler object per each call. The only purpose for this object is to use in composition-\>GetEventReceiver()-\>EVENT_NAME.**Detach** and cancel the registration that returning that perticular handler object. If **Detach** returns **false**, either this registration has already been canceled, or this registration doesn't happen in this event.
|
||||
In the event registration object you will find a lot of fields for events, for example,**leftButtonDown**. There are 3 methods for subscribing an event:
|
||||
- composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachMethod**: subscribe an event using an object and a member function pointer.
|
||||
- composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachFunction**: subscribe an event using a function pointer or a**vl::Func\<...\>**functor.
|
||||
- composition-\>GetEventReceiver()-\>EVENT_NAME.**AttachLambda**: subscribe an event using a lambda expression or other functors.All 3 methods returns a new handler object per each call. The only purpose for this object is to use in composition-\>GetEventReceiver()-\>EVENT_NAME.**Detach**and cancel the registration that returning that perticular handler object. If**Detach**returns**false**, either this registration has already been canceled, or this registration doesn't happen in this event.
|
||||
|
||||
In the event callback function, the first argument is always **GuiGraphicsComposition*** which is the owner of the event registration object, the second argument varies in different events.
|
||||
In the event callback function, the first argument is always**GuiGraphicsComposition***which is the owner of the event registration object, the second argument varies in different events.
|
||||
|
||||
In GacUI XML Resource, raw input events are treated like attributes of a composition. You can either specify a method name of the current instance, or specify a piece of code to run. Please check out [this page](../../.././gacui/xmlres/instance/events.md) for details.
|
||||
In GacUI XML Resource, raw input events are treated like attributes of a composition. You can either specify a method name of the current instance, or specify a piece of code to run. Please check out[this page](../../.././gacui/xmlres/instance/events.md)for details.
|
||||
|
||||
## Events and Parent Chain
|
||||
|
||||
Most of the events are not only raised on the composition that receives the input, but also all the way to the root in the parent chain, which means after the event is raised on the source composition, it is then raised on its parent, and its parent's parent until the end.
|
||||
|
||||
Such process could be detected using members of the second argument: - **compositionSource**: the composition right under the mouse, which is the original event raiser. When the event raises through the parent chain, this member doesn't change. - **eventSource**: If the **compositionSource** has an associated event registration object, **eventSource** is **compositionSource**. Otherwise, **eventSource** is the nearest parent composition that has an associated event registration object. - **handled**: you can set this member in the event callback function to **true** to stop the event from going through more further in the parent chain. Meanwhile, the first argument is the composition who owns the event registration object the callback function is registered to. When the event raises through the parent chain, the first argument becomes the current "parent".
|
||||
Such process could be detected using members of the second argument:
|
||||
- **compositionSource**: the composition right under the mouse, which is the original event raiser. When the event raises through the parent chain, this member doesn't change.
|
||||
- **eventSource**: If the**compositionSource**has an associated event registration object,**eventSource**is**compositionSource**. Otherwise,**eventSource**is the nearest parent composition that has an associated event registration object.
|
||||
- **handled**: you can set this member in the event callback function to**true**to stop the event from going through more further in the parent chain.Meanwhile, the first argument is the composition who owns the event registration object the callback function is registered to. When the event raises through the parent chain, the first argument becomes the current "parent".
|
||||
|
||||
## Mouse Events
|
||||
|
||||
### Button and Wheel Events
|
||||
|
||||
GacUI offers the following button events: - leftButtonDown - leftButtonUp - leftButtonDoubleClick - middleButtonDown - middleButtonUp - middleButtonDoubleClick - rightButtonDown - rightButtonUp - rightButtonDoubleClick - horizontalWheel - verticalWheel mapping to the 5 standard buttons of a mouse. But a typical mouse today, middle button and vertical wheel are merged together, horizontal wheel are usually missing.
|
||||
GacUI offers the following button events:
|
||||
- leftButtonDown
|
||||
- leftButtonUp
|
||||
- leftButtonDoubleClick
|
||||
- middleButtonDown
|
||||
- middleButtonUp
|
||||
- middleButtonDoubleClick
|
||||
- rightButtonDown
|
||||
- rightButtonUp
|
||||
- rightButtonDoubleClick
|
||||
- horizontalWheel
|
||||
- verticalWheelmapping to the 5 standard buttons of a mouse. But a typical mouse today, middle button and vertical wheel are merged together, horizontal wheel are usually missing.
|
||||
|
||||
The type of the second argument is **vl::presentation::compositions::GuiMouseEventArgs&**, or **presentation::composition::GuiMouseEventArgs*** in **Workflow**.
|
||||
The type of the second argument is**vl::presentation::compositions::GuiMouseEventArgs&**, or**presentation::composition::GuiMouseEventArgs***in**Workflow**.
|
||||
|
||||
Mouse button and wheel events are raised on captured composition, or the composition right under the mouse when no composition is captured, and then go through the parent chain, which is stoppable by setting **handled** to **true**.
|
||||
Mouse button and wheel events are raised on captured composition, or the composition right under the mouse when no composition is captured, and then go through the parent chain, which is stoppable by setting**handled**to**true**.
|
||||
|
||||
Other members contains the information of the event: - **ctrl**: **true** if the CTRL key is pressing. - **shift**: **true** if the SHIFT key is pressing. - **left**: **true** if the mouse left button is pressing. - **middle**: **true** if the mouse middle button is pressing. - **right**: **true** if the mouse right button is pressing. - **x** and **y**: the relative coordinate to **first callback argument**. - **wheel**: direction and distance of the wheel. A positive number means the wheel is rotating towards right or down. The unit of the rotation is 120 for today's typical mouse.
|
||||
Other members contains the information of the event:
|
||||
- **ctrl**:**true**if the CTRL key is pressing.
|
||||
- **shift**:**true**if the SHIFT key is pressing.
|
||||
- **left**:**true**if the mouse left button is pressing.
|
||||
- **middle**:**true**if the mouse middle button is pressing.
|
||||
- **right**:**true**if the mouse right button is pressing.
|
||||
- **x**and**y**: the relative coordinate to**first callback argument**.
|
||||
- **wheel**: direction and distance of the wheel. A positive number means the wheel is rotating towards right or down. The unit of the rotation is 120 for today's typical mouse.
|
||||
|
||||
### Moving Events
|
||||
|
||||
GacUI offers the following button events: - mouseMove - mouseEnter - mouseLeave mapping to the 5 standard buttons of a mouse. But a typical mouse today, middle button and vertical wheel are merged together, horizontal wheel are usually missing.
|
||||
GacUI offers the following button events:
|
||||
- mouseMove
|
||||
- mouseEnter
|
||||
- mouseLeavemapping to the 5 standard buttons of a mouse. But a typical mouse today, middle button and vertical wheel are merged together, horizontal wheel are usually missing.
|
||||
|
||||
**mouseEnter** happens when the mouse moves into a composition. **mouseLeave** happens when the mouse moves out of a composition. When a mouse moves from one composition to its child composition, it doesn't count as leaving the original composition, it is still in the original composition and its child composition.
|
||||
**mouseEnter**happens when the mouse moves into a composition.**mouseLeave**happens when the mouse moves out of a composition. When a mouse moves from one composition to its child composition, it doesn't count as leaving the original composition, it is still in the original composition and its child composition.
|
||||
|
||||
**mouseMove** happens when the mouse moves. It is raised on captured composition, or the composition right under the mouse when no composition is captured, and then go through the parent chain, which is stoppable by setting **handled** to **true**.
|
||||
**mouseMove**happens when the mouse moves. It is raised on captured composition, or the composition right under the mouse when no composition is captured, and then go through the parent chain, which is stoppable by setting**handled**to**true**.
|
||||
|
||||
### Capturing
|
||||
|
||||
When a button down event happens, the **compositionSource** is captured. A captured composition becomes the **compositionSource** of all following mouse events happen in the containing window (or menu, popup, etc...), including button up events.
|
||||
When a button down event happens, the**compositionSource**is captured. A captured composition becomes the**compositionSource**of all following mouse events happen in the containing window (or menu, popup, etc...), including button up events.
|
||||
|
||||
After the button up event happens, the capturing is released.
|
||||
|
||||
### Moving or deleting controls or compositions during mouse events.
|
||||
|
||||
Some times you may want to change the control tree structure in a callback of mouse events, (including **Clicked** in buttons).
|
||||
Some times you may want to change the control tree structure in a callback of mouse events, (including**Clicked**in buttons).
|
||||
|
||||
This is tricky because, mouse events are not just sent to this composition, it is sent to all its parent compositions. Even when **handled** is set to **true**, there is still something to do after the callback function ends.
|
||||
This is tricky because, mouse events are not just sent to this composition, it is sent to all its parent compositions. Even when**handled**is set to**true**, there is still something to do after the callback function ends.
|
||||
|
||||
When you move or delete controls or compositions that affect the parent chain, **GacUI will stably CRASH**.
|
||||
When you move or delete controls or compositions that affect the parent chain,**GacUI will stably CRASH**.
|
||||
|
||||
In order to solve this issue, **GetApplication()-\>InvokeInMainThread** is your friend. Whenever you call this function, the callback to **InvokeInMainThread** will run right after the current series of events. That is a very safe point to restructure your controls or compositions.
|
||||
In order to solve this issue,**GetApplication()-\>InvokeInMainThread**is your friend. Whenever you call this function, the callback to**InvokeInMainThread**will run right after the current series of events. That is a very safe point to restructure your controls or compositions.
|
||||
|
||||
For example, if you customize the tab control to have a close button in each tab page:
|
||||
```
|
||||
void MyTabPage::buttonCloseClicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
|
||||
{
|
||||
// this is still in the chain of mouse button events,
|
||||
// so InvokeInMainThread is required to delete MyTabPage.
|
||||
GetApplication()->InvokeInMainThread(this->GetRelatedControlHost(), [=]()
|
||||
{
|
||||
this->GetOwnerTab()->GetPages().Remove(this);
|
||||
SafeDeleteControl(this);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
For example, if you customize the tab control to have a close button in each tab page: ``` void MyTabPage::buttonCloseClicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments) { // this is still in the chain of mouse button events, // so InvokeInMainThread is required to delete MyTabPage. GetApplication()->InvokeInMainThread(this->GetRelatedControlHost(), [=]() { this->GetOwnerTab()->GetPages().Remove(this); SafeDeleteControl(this); }); } ```
|
||||
|
||||
## Focus Events
|
||||
|
||||
GacUI offers the following button events: - gotFocus - lostFocus - caretNotify
|
||||
GacUI offers the following button events:
|
||||
- gotFocus
|
||||
- lostFocus
|
||||
- caretNotify
|
||||
|
||||
The type of the second argument is **vl::presentation::compositions::GuiEventArgs&**, or **presentation::composition::GuiEventArgs*** in **Workflow**.
|
||||
The type of the second argument is**vl::presentation::compositions::GuiEventArgs&**, or**presentation::composition::GuiEventArgs***in**Workflow**.
|
||||
|
||||
A focus composition is the **FocusableComposition** of a control that has focus. Control like buttons will take focus after it is clicked, you can also call **SetFocus** to move focus to a control.
|
||||
A focus composition is the**FocusableComposition**of a control that has focus. Control like buttons will take focus after it is clicked, you can also call**SetFocus**to move focus to a control.
|
||||
|
||||
When a control get its focus, its **FocusableComposition** has the focus. If you are writing a control template, you can set any composition to the **FocusableComposition** property of the control template, and it becomes the **FocusableComposition** of the control.
|
||||
When a control get its focus, its**FocusableComposition**has the focus. If you are writing a control template, you can set any composition to the**FocusableComposition**property of the control template, and it becomes the**FocusableComposition**of the control.
|
||||
|
||||
A window has only one focused control. **gotFocus** raises on a composition when it is focused. **lostFocus** raises on a previous focused composition when it lost the focus.
|
||||
A window has only one focused control.**gotFocus**raises on a composition when it is focused.**lostFocus**raises on a previous focused composition when it lost the focus.
|
||||
|
||||
**caretNotify** is keep raising on the focused control every half second. If a control wants to render an input caret, it needs to subscribe to **caretNotify**, and than changing the input caret between visible and invisible state when this event happens.
|
||||
**caretNotify**is keep raising on the focused control every half second. If a control wants to render an input caret, it needs to subscribe to**caretNotify**, and than changing the input caret between visible and invisible state when this event happens.
|
||||
|
||||
COMPOSITION-\>**GetRelatedGraphicsHost**()-\>**SetCaretPoint** is useful to tell the system where to show the little window for the input method. This function is strongly recommended to be called by the focused control to avoid state corruption.
|
||||
COMPOSITION-\>**GetRelatedGraphicsHost**()-\>**SetCaretPoint**is useful to tell the system where to show the little window for the input method. This function is strongly recommended to be called by the focused control to avoid state corruption.
|
||||
|
||||
If the window itself gets or loses focus, related events are raised on the window, events described here are not affected.
|
||||
|
||||
## Keyboard Events
|
||||
|
||||
GacUI offers the following button events: - previewKey - keyDown - keyUp
|
||||
GacUI offers the following button events:
|
||||
- previewKey
|
||||
- keyDown
|
||||
- keyUp
|
||||
|
||||
The type of the second argument is **vl::presentation::compositions::GuiKeyEventArgs&**, or **presentation::composition::GuiKeyEventArgs*** in **Workflow**.
|
||||
The type of the second argument is**vl::presentation::compositions::GuiKeyEventArgs&**, or**presentation::composition::GuiKeyEventArgs***in**Workflow**.
|
||||
|
||||
Keyboard events are raised on the focused composition, and then go through the parent chain, which is stoppable by setting **handled** to **true**.
|
||||
Keyboard events are raised on the focused composition, and then go through the parent chain, which is stoppable by setting**handled**to**true**.
|
||||
|
||||
**previewKey** is raised before any other keyboard events. If **handled** is set to **true**, not only the parent chain will stop, the following keyboard event will also be canceled.
|
||||
**previewKey**is raised before any other keyboard events. If**handled**is set to**true**, not only the parent chain will stop, the following keyboard event will also be canceled.
|
||||
|
||||
**code** member of the second argument maps to an item in **vl::presentation::VKEY** enum.
|
||||
**code**member of the second argument maps to an item in**vl::presentation::VKEY**enum.
|
||||
|
||||
Other members contains the information of the event: - **ctrl**: **true** if the CTRL key is pressing. - **shift**: **true** if the SHIFT key is pressing. - **alt**: **true** if the ALT button is pressing. - **capslock**: **true** if the CAPSLOCK button is activated. - **autoRepeatKeyDown**: **true** if this event is generated because of holding a key.
|
||||
Other members contains the information of the event:
|
||||
- **ctrl**:**true**if the CTRL key is pressing.
|
||||
- **shift**:**true**if the SHIFT key is pressing.
|
||||
- **alt**:**true**if the ALT button is pressing.
|
||||
- **capslock**:**true**if the CAPSLOCK button is activated.
|
||||
- **autoRepeatKeyDown**:**true**if this event is generated because of holding a key.
|
||||
|
||||
## Input Events
|
||||
|
||||
GacUI offers the following button events: - previewCharInput - charInput
|
||||
GacUI offers the following button events:
|
||||
- previewCharInput
|
||||
- charInput
|
||||
|
||||
The type of the second argument is **vl::presentation::compositions::GuiCharEventArgs&**, or **presentation::composition::GuiCharEventArgs*** in **Workflow**.
|
||||
The type of the second argument is**vl::presentation::compositions::GuiCharEventArgs&**, or**presentation::composition::GuiCharEventArgs***in**Workflow**.
|
||||
|
||||
Input events are raised on the focused composition, and then go through the parent chain, which is stoppable by setting **handled** to **true**.
|
||||
Input events are raised on the focused composition, and then go through the parent chain, which is stoppable by setting**handled**to**true**.
|
||||
|
||||
**previewCharInput** is raised before any other keyboard events. If **handled** is set to **true**, not only the parent chain will stop, the following keyboard event will also be canceled.
|
||||
**previewCharInput**is raised before any other keyboard events. If**handled**is set to**true**, not only the parent chain will stop, the following keyboard event will also be canceled.
|
||||
|
||||
**code** member of the second argument is a **wchar_t** that being typed into the control. In Windows, **wchar_t** is a UTF-16 code point. In other platform, **wchar_t** is a UTF-32 code point.
|
||||
**code**member of the second argument is a**wchar_t**that being typed into the control. In Windows,**wchar_t**is a UTF-16 code point. In other platform,**wchar_t**is a UTF-32 code point.
|
||||
|
||||
Other members contains the information of the event: - **ctrl**: **true** if the CTRL key is pressing. - **shift**: **true** if the SHIFT key is pressing. - **alt**: **true** if the ALT button is pressing. - **capslock**: **true** if the CAPSLOCK button is activated.
|
||||
Other members contains the information of the event:
|
||||
- **ctrl**:**true**if the CTRL key is pressing.
|
||||
- **shift**:**true**if the SHIFT key is pressing.
|
||||
- **alt**:**true**if the ALT button is pressing.
|
||||
- **capslock**:**true**if the CAPSLOCK button is activated.
|
||||
|
||||
## Other Events
|
||||
|
||||
GacUI offers the following button events: - clipboardNotify - renderTargetChanged
|
||||
GacUI offers the following button events:
|
||||
- clipboardNotify
|
||||
- renderTargetChanged
|
||||
|
||||
The type of the second argument is **vl::presentation::compositions::GuiEventArgs&**, or **presentation::composition::GuiEventArgs*** in **Workflow**.
|
||||
The type of the second argument is**vl::presentation::compositions::GuiEventArgs&**, or**presentation::composition::GuiEventArgs***in**Workflow**.
|
||||
|
||||
When content in the system clipboard changes, **clipboardNotify** raises on every compositions.
|
||||
When content in the system clipboard changes,**clipboardNotify**raises on every compositions.
|
||||
|
||||
When the render target is changed, this may because a composition is added to or remove from a window, or the window itself loses and recreates its render target, **renderTargetChanged** raises on the affected root composition and all direct or indirect child compositions.
|
||||
When the render target is changed, this may because a composition is added to or remove from a window, or the window itself loses and recreates its render target,**renderTargetChanged**raises on the affected root composition and all direct or indirect child compositions.
|
||||
|
||||
If a composition is not added to a window, its render target is **null**.
|
||||
If a composition is not added to a window, its render target is**null**.
|
||||
|
||||
|
||||
@@ -1,82 +1,85 @@
|
||||
# \<Flow\> and \<FlowItem\>
|
||||
|
||||
**\<Flow/\>** arrange all direct children **\<FlowItem/\>** compositions in multiple rows with auto line wrapping.
|
||||
**\<Flow/\>**arrange all direct children**\<FlowItem/\>**compositions in multiple rows with auto line wrapping.
|
||||
|
||||
**\<FlowItem/\>**::MinSizeLimitation is **LimitToElementAndChildren** by default.
|
||||
**\<FlowItem/\>**::MinSizeLimitation is**LimitToElementAndChildren**by default.
|
||||
|
||||
## Properties
|
||||
|
||||
A few more properties are provided by **\<Flow/\>** and **\<FlowItem/\>** to control the details of how to ordering **\<FlowItem/\>**.
|
||||
A few more properties are provided by**\<Flow/\>**and**\<FlowItem/\>**to control the details of how to ordering**\<FlowItem/\>**.
|
||||
|
||||
**\<FlowItem/\>** is not a **\<Bounds/\>**, there is no writable **ExpectedBounds** and **AlignmentToParent** in **\<FlowItem/\>**.
|
||||
**\<FlowItem/\>**is not a**\<Bounds/\>**, there is no writable**ExpectedBounds**and**AlignmentToParent**in**\<FlowItem/\>**.
|
||||
|
||||
### \<Flow\>::Axis
|
||||
|
||||
The default value is **\<DefaultAxis/\>**, which equivalents to **\<Axis AxisDirection="RightDown"/\>**.
|
||||
The default value is**\<DefaultAxis/\>**, which equivalents to**\<Axis AxisDirection="RightDown"/\>**.
|
||||
|
||||
**LeftDown**, **RightDown**, **LeftUp**, **RightUp**, **DownLeft**, **DownRight**, **UpLeft** and **UpRight** are all valid values for the **AxisDirection** property.
|
||||
**LeftDown**,**RightDown**,**LeftUp**,**RightUp**,**DownLeft**,**DownRight**,**UpLeft**and**UpRight**are all valid values for the**AxisDirection**property.
|
||||
|
||||
Among these values, the first word describes the direction how **\<FlowItem/\>** are line up one by one, the second word describes the direction how auto line wrapping does. For example, **RightDown** means the next item is put on the **right** side of the previous item, and when there is no more space for this item in the current row, it creates a new row on the **down** side of the current row.
|
||||
Among these values, the first word describes the direction how**\<FlowItem/\>**are line up one by one, the second word describes the direction how auto line wrapping does. For example,**RightDown**means the next item is put on the**right**side of the previous item, and when there is no more space for this item in the current row, it creates a new row on the**down**side of the current row.
|
||||
|
||||
### \<Flow\>::Alignment
|
||||
|
||||
The default value is **Left**.
|
||||
The default value is**Left**.
|
||||
|
||||
**Left**, **Center**, **Right** and **Extend** are all valid values for the this property.
|
||||
**Left**,**Center**,**Right**and**Extend**are all valid values for the this property.
|
||||
|
||||
This property describes how **\<FlowItem/\>** are positioned in one row.
|
||||
This property describes how**\<FlowItem/\>**are positioned in one row.
|
||||
|
||||
### \<Flow\>::RowPadding and \<Flow\>::ColumnPadding
|
||||
|
||||
The default value is 0.
|
||||
|
||||
This property keeps an distance between each **\<FlowItem/\>**.
|
||||
This property keeps an distance between each**\<FlowItem/\>**.
|
||||
|
||||
**IMPORTANT**: **Row** here doesn't necessary mean a line in horizontal direction, it depends on the value of the **Axis** property.
|
||||
**IMPORTANT**:**Row**here doesn't necessary mean a line in horizontal direction, it depends on the value of the**Axis**property.
|
||||
|
||||
### \<Flow\>::ExtraMargin
|
||||
|
||||
The default value is 0 for all its components.
|
||||
|
||||
This property keeps an distance between **\<Flow/\>** and **\<FlowItem/\>**.
|
||||
This property keeps an distance between**\<Flow/\>**and**\<FlowItem/\>**.
|
||||
|
||||
### \<FlowItem\>::ExtraMargin
|
||||
|
||||
The default value is 0 for all its components.
|
||||
|
||||
This property adds a border to a **\<FlowItem/\>**.
|
||||
This property adds a border to a**\<FlowItem/\>**.
|
||||
|
||||
**IMPORTANT**: **ExtraMargin** does not affect how **other \<FlowItem/\>** is positioned. Instead, after the position of a **\<FlowItem/\>** is decided, **ExtraMargin** kicks in and add a border to enlarge it.
|
||||
**IMPORTANT**:**ExtraMargin**does not affect how**other \<FlowItem/\>**is positioned. Instead, after the position of a**\<FlowItem/\>**is decided,**ExtraMargin**kicks in and add a border to enlarge it.
|
||||
|
||||
Adding an **ExtraMargin** to a **\<FlowItem/\>** does not increase the minimum size of its parent **\<Flow/\>**.
|
||||
Adding an**ExtraMargin**to a**\<FlowItem/\>**does not increase the minimum size of its parent**\<Flow/\>**.
|
||||
|
||||
### \<FlowItem\>::FlowOption
|
||||
|
||||
The default value is **baseline:FromBottom distance:0**.
|
||||
The default value is**baseline:FromBottom distance:0**.
|
||||
|
||||
This property describes how **\<FlowItem/\>** are positioned in one row.
|
||||
This property describes how**\<FlowItem/\>**are positioned in one row.
|
||||
|
||||
**baseline** could be **FromTop**, **FromBottom** or **Percentage**: - **FromTop**: the **\<FlowItem/\>** keeps the **distance** from the top of the row. - **FromBottom**: the **\<FlowItem/\>** keeps the **distance** from the bottom of the row. - **Percentage**: the **\<FlowItem/\>** keeps the distahce, which is **pencentage** of its height, from the top of the row.
|
||||
**baseline**could be**FromTop**,**FromBottom**or**Percentage**:
|
||||
- **FromTop**: the**\<FlowItem/\>**keeps the**distance**from the top of the row.
|
||||
- **FromBottom**: the**\<FlowItem/\>**keeps the**distance**from the bottom of the row.
|
||||
- **Percentage**: the**\<FlowItem/\>**keeps the distahce, which is**pencentage**of its height, from the top of the row.
|
||||
|
||||
**IMPORTANT**: **Top** here doesn't necessary mean the top border of a row, it depends on the value of the **Axis** property.
|
||||
**IMPORTANT**:**Top**here doesn't necessary mean the top border of a row, it depends on the value of the**Axis**property.
|
||||
|
||||
## Adding Flow Items
|
||||
|
||||
### \<Flow\>::Children()
|
||||
|
||||
When a new **\<FlowItem/\>** is added to **\<Flow/\>** as a child, this **\<FlowItem/\>** is always appended to the end of the last row, regardless of its position in **\<Flow\>::Children**.
|
||||
When a new**\<FlowItem/\>**is added to**\<Flow/\>**as a child, this**\<FlowItem/\>**is always appended to the end of the last row, regardless of its position in**\<Flow\>::Children**.
|
||||
|
||||
### \<Flow\>::InsertFlowItem(index, item)
|
||||
|
||||
To control the position of a **\<FlowItem/\>** in the auto-wrapped line, call **\<Flow\>::InsertFlowItem()** instead of **\<Flow\>::Children()**.
|
||||
To control the position of a**\<FlowItem/\>**in the auto-wrapped line, call**\<Flow\>::InsertFlowItem()**instead of**\<Flow\>::Children()**.
|
||||
|
||||
This function also adds a **\<FlowItem/\>** to the **\<Flow/\>**, but it allows the position of this **\<FlowItem/\>** in the auto-wrapped line to be specified, instead of adding it to the end of the last row.
|
||||
This function also adds a**\<FlowItem/\>**to the**\<Flow/\>**, but it allows the position of this**\<FlowItem/\>**in the auto-wrapped line to be specified, instead of adding it to the end of the last row.
|
||||
|
||||
### \<Flow\>::GetFlowItems()
|
||||
|
||||
Call this function to get all direct children **\<FlowItem/\>** in the line order.
|
||||
Call this function to get all direct children**\<FlowItem/\>**in the line order.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Flow) .
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Flow).
|
||||
|
||||
|
||||
@@ -1,18 +1,48 @@
|
||||
# Compositions
|
||||
|
||||
[Composition](../../.././gacui/kb/compositions.md) offer layout algorithms based on constraints. Usually, developers using GacUI places nested controls and compositions in a window, by defining constraints between compositions, the window knows its minimum size, and how to change sizes of child controls when the window is resizing.
|
||||
[Composition](../../.././gacui/kb/compositions.md)offer layout algorithms based on constraints. Usually, developers using GacUI places nested controls and compositions in a window, by defining constraints between compositions, the window knows its minimum size, and how to change sizes of child controls when the window is resizing.
|
||||
|
||||
There are a lot of predefined compositions as follows, each defines a kind of constraint: - GuiGraphicsComposition - GuiWindowComposition - \<Bounds\> - \<Stack\> - \<RepeatStack\> - \<Flow\> - \<RepeatFlow\> - \<Table\> - \<SharedSizeRoot\> - \<SharedSizeItem\> - GuiResponsiveCompositionBase - \<ResponsiveView\> - \<ResponsiveFixed\> - \<ResponsiveStack\> - \<ResponsiveGroup\> - \<ResponsiveShared\> - \<ResponsiveContainer\> - \<StackItem\> - \<FlowItem\> - \<Cell\> - GuiTableSplitterComposition - \<RowSplitter\> - \<ColumnSplitter\> - \<SideAligned\> - \<PartialView\> - GuiVirtualRepeatCompositionBase - \<RepeatFreeHeightItem\> - \<RepeatFixedHeightItem\> - \<RepeatFixedSizeMultiColumnItem\> - \<RepeatFixedHeightMultiColumnItem\>
|
||||
There are a lot of predefined compositions as follows, each defines a kind of constraint:
|
||||
- GuiGraphicsComposition
|
||||
- GuiWindowComposition
|
||||
- \<Bounds\>
|
||||
- \<Stack\>
|
||||
- \<RepeatStack\>
|
||||
- \<Flow\>
|
||||
- \<RepeatFlow\>
|
||||
- \<Table\>
|
||||
- \<SharedSizeRoot\>
|
||||
- \<SharedSizeItem\>
|
||||
- GuiResponsiveCompositionBase
|
||||
- \<ResponsiveView\>
|
||||
- \<ResponsiveFixed\>
|
||||
- \<ResponsiveStack\>
|
||||
- \<ResponsiveGroup\>
|
||||
- \<ResponsiveShared\>
|
||||
- \<ResponsiveContainer\>
|
||||
- \<StackItem\>
|
||||
- \<FlowItem\>
|
||||
- \<Cell\>
|
||||
- GuiTableSplitterComposition
|
||||
- \<RowSplitter\>
|
||||
- \<ColumnSplitter\>
|
||||
- \<SideAligned\>
|
||||
- \<PartialView\>
|
||||
- GuiVirtualRepeatCompositionBase
|
||||
- \<RepeatFreeHeightItem\>
|
||||
- \<RepeatFixedHeightItem\>
|
||||
- \<RepeatFixedSizeMultiColumnItem\>
|
||||
- \<RepeatFixedHeightMultiColumnItem\>
|
||||
|
||||
Here we introduce common constraints and configuration of all compositions first.
|
||||
|
||||
## TransparentToMouse property
|
||||
|
||||
The default value is **false**.
|
||||
The default value is**false**.
|
||||
|
||||
If it is set to **true**, this composition becomes transparent to the mouse. When a mouse clicks on this composition, the click just go through this composition and hit a non-transparent one under this composition.
|
||||
If it is set to**true**, this composition becomes transparent to the mouse. When a mouse clicks on this composition, the click just go through this composition and hit a non-transparent one under this composition.
|
||||
|
||||
**Note**: by setting it to **true**, it doesn't makes child compositions become transparent to the mouse. If you want a whole composition tree to be transparent to the mouse, every single composition in this tree must have this property set to **true**.
|
||||
**Note**: by setting it to**true**, it doesn't makes child compositions become transparent to the mouse. If you want a whole composition tree to be transparent to the mouse, every single composition in this tree must have this property set to**true**.
|
||||
|
||||
## AssociatedCursor property
|
||||
|
||||
@@ -20,97 +50,119 @@ This property defines how the cursor should look like when the cursor is over th
|
||||
|
||||
If this property is not set, it will ask its parent composition for a value.
|
||||
|
||||
In **GacUI XML Resource**, the type of this property is **presentation::INativeCursor::SystemCursorType**. The value could be any item of this enum.
|
||||
In**GacUI XML Resource**, the type of this property is**presentation::INativeCursor::SystemCursorType**. The value could be any item of this enum.
|
||||
|
||||
## AssociatedHitTestResult property
|
||||
|
||||
The property defines how the window should behave when the mouse is interacting with this composition.
|
||||
|
||||
The type of this property is **presentation::INativeWindowListener::HitTestResult**. The value could be any item of this enum.
|
||||
The type of this property is**presentation::INativeWindowListener::HitTestResult**. The value could be any item of this enum.
|
||||
|
||||
Usually this property is used when implementing a control template for **\<Window/\>**. For example, the window template will have a close button and **ButtonClose** is set to the **AssociatedHitTestResult** property of this button's **BoundsComposition**. When the mouse clicks this button, the OS will know that this button is for closing the window, and then raise a sequence of events and close the window if it is not interrupted. No code is needed for the **Clicked** event of this button.
|
||||
Usually this property is used when implementing a control template for**\<Window/\>**. For example, the window template will have a close button and**ButtonClose**is set to the**AssociatedHitTestResult**property of this button's**BoundsComposition**. When the mouse clicks this button, the OS will know that this button is for closing the window, and then raise a sequence of events and close the window if it is not interrupted. No code is needed for the**Clicked**event of this button.
|
||||
|
||||
## Visible property
|
||||
|
||||
The default value is **true**.
|
||||
The default value is**true**.
|
||||
|
||||
If it is set to **false**, anything inside this composition will not be rendered, **but they still affect the sizing** as they are visible.
|
||||
If it is set to**false**, anything inside this composition will not be rendered,**but they still affect the sizing**as they are visible.
|
||||
|
||||
## Box Model
|
||||
|
||||

|
||||
|
||||
**DO NOT** control layout by code, **DO** control layout by assigning proper values to properties mentioned below. the layout will be fixed as soon as possible after properties of elements are changed, and it is fast enough, but the timing is not guaranteed.
|
||||
**DO NOT**control layout by code,**DO**control layout by assigning proper values to properties mentioned below. the layout will be fixed as soon as possible after properties of elements are changed, and it is fast enough, but the timing is not guaranteed.
|
||||
|
||||
Any attempts to read the position of size of composition by programming could lead to unexpected result.
|
||||
|
||||
### Minimum size of the composition
|
||||
|
||||
The minimum size is controlled by the following properties: - **PreferredMinSize** - **OwnedElement** when **MinSizeLimitation** is **LimitToElement** or **LimitToElementAndChildren** - **Children** when **MinSizeLimitation** is **LimitToElementAndChildren** And also by the following properties that only exist in **GuiBoundsComposition** and its derived classes: - **ExpectedBounds**'s size - Children's **AlignmentToParent** when **MinSizeLimitation** is **LimitToElementAndChildren**
|
||||
The minimum size is controlled by the following properties:
|
||||
- **PreferredMinSize**
|
||||
- **OwnedElement**when**MinSizeLimitation**is**LimitToElement**or**LimitToElementAndChildren**
|
||||
- **Children**when**MinSizeLimitation**is**LimitToElementAndChildren**And also by the following properties that only exist in**GuiBoundsComposition**and its derived classes:
|
||||
- **ExpectedBounds**'s size
|
||||
- Children's**AlignmentToParent**when**MinSizeLimitation**is**LimitToElementAndChildren**
|
||||
|
||||
A composition has a default minimum size to 0.
|
||||
|
||||
By assigning an element to the **OwnedElement** property, the element is binded to this composition. The element is rendered using the composition's position and size.
|
||||
By assigning an element to the**OwnedElement**property, the element is binded to this composition. The element is rendered using the composition's position and size.
|
||||
|
||||
Sometimes the element requires a minimum size to render its full content (typically for **SolidLabel** without enabling trailing ellipses). To assign the minimum size to this composition, simply just set **MinSizeLimitation** to **LimitToElement** or **LimitToElementAndChildren**.
|
||||
Sometimes the element requires a minimum size to render its full content (typically for**SolidLabel**without enabling trailing ellipses). To assign the minimum size to this composition, simply just set**MinSizeLimitation**to**LimitToElement**or**LimitToElementAndChildren**.
|
||||
|
||||
If this composition has children, there will also be a minimum size to render all children. To assign the minimum size to this composition, simply just set **MinSizeLimitation** to **LimitToElementAndChildren**.
|
||||
If this composition has children, there will also be a minimum size to render all children. To assign the minimum size to this composition, simply just set**MinSizeLimitation**to**LimitToElementAndChildren**.
|
||||
|
||||
You can also assign a minimum size to this composition using the **PreferredMinSize** property.
|
||||
You can also assign a minimum size to this composition using the**PreferredMinSize**property.
|
||||
|
||||
### Position of the composition
|
||||
|
||||
The position is controlled by the following properties: - **AlignmentToParent**, defaults to (-1,-1,-1,-1). Any component of **AlignmentToParent** must be -1 or non-negative. **AlignmentToParent** is the gap between this composition and its parent compositon. - **ExpectedBounds**, defaults to (0,0,0,0). - **InternalMargin** of the parent composition, defaults to (0,0,0,0). Any component of **InternalMargin** must be non-negative. **InternalMargin** adds a gap between this component and its children compositions. A component of **InternalMargin** is considered when the corresponding component of **AlignmentToParent** of a child composition is **-1**.
|
||||
The position is controlled by the following properties:
|
||||
- **AlignmentToParent**, defaults to (-1,-1,-1,-1). Any component of**AlignmentToParent**must be -1 or non-negative.**AlignmentToParent**is the gap between this composition and its parent compositon.
|
||||
- **ExpectedBounds**, defaults to (0,0,0,0).
|
||||
- **InternalMargin**of the parent composition, defaults to (0,0,0,0). Any component of**InternalMargin**must be non-negative.**InternalMargin**adds a gap between this component and its children compositions. A component of**InternalMargin**is considered when the corresponding component of**AlignmentToParent**of a child composition is**-1**.
|
||||
|
||||
Considering **left** and **right** of **AlignmentToParent**. - If both are not -1, the gap between this composition and its parent is defined by **AlignmentToParent**. - If **left** is -1 and **right** is not, the right gap is defined by **AlignmentToParent**, the left gap is decided by the component's width. - If **left** is not -1 and **right** is not, the left gap is defined by **AlignmentToParent**, the right gap is decided by the component's width. - If both are -1, the left gap is defined by **ExpectedBounds** combining with its parent's **InternalMargin**, the right gap is decided by the component's width. **top**, **bottom** and height are similar to what is described above.
|
||||
Considering**left**and**right**of**AlignmentToParent**.
|
||||
- If both are not -1, the gap between this composition and its parent is defined by**AlignmentToParent**.
|
||||
- If**left**is -1 and**right**is not, the right gap is defined by**AlignmentToParent**, the left gap is decided by the component's width.
|
||||
- If**left**is not -1 and**right**is not, the left gap is defined by**AlignmentToParent**, the right gap is decided by the component's width.
|
||||
- If both are -1, the left gap is defined by**ExpectedBounds**combining with its parent's**InternalMargin**, the right gap is decided by the component's width.**top**,**bottom**and height are similar to what is described above.
|
||||
|
||||
**AlignmentToParent** also affects the minimum size of the parent composition if **MinSizeLimitation** of the parent composition is set to **LimitToElementAndChildren**.
|
||||
**AlignmentToParent**also affects the minimum size of the parent composition if**MinSizeLimitation**of the parent composition is set to**LimitToElementAndChildren**.
|
||||
|
||||
**NOTE**: some compositions like **\<SideAligned/\>** or **\<PartialView/\>** ignores **AlignmentToParent**.
|
||||
**NOTE**: some compositions like**\<SideAligned/\>**or**\<PartialView/\>**ignores**AlignmentToParent**.
|
||||
|
||||
### Keeping a button at the right-bottom corner of the window
|
||||
|
||||
This is very straightforward: ``` <Button> <att.BoundsComposition AlignmentToParent="left:-1 top:-1 right:5 bottom:5"/> </Button> ```
|
||||
This is very straightforward:
|
||||
```
|
||||
<Button>
|
||||
<att.BoundsComposition AlignmentToParent="left:-1 top:-1 right:5 bottom:5"/>
|
||||
</Button>
|
||||
```
|
||||
|
||||
|
||||
By doing this, the button will keep its right 5 pixel (96 dpi) away from its parent's right, also its bottom 5 pixel (96 dpi) away from its parent's bottom. When the size of its parent changes, the button will stick to the right-bottom corner.
|
||||
|
||||
**NOTE**: you are recommended to use **\<Table/\>** when you can, since the size of the button could change because it has different text under different OS language configuration. **\<Table/\>** helps to organize the button and the content above the button, or when there are multiple button on the right-bottom size.
|
||||
**NOTE**: you are recommended to use**\<Table/\>**when you can, since the size of the button could change because it has different text under different OS language configuration.**\<Table/\>**helps to organize the button and the content above the button, or when there are multiple button on the right-bottom size.
|
||||
|
||||
## Data Binding on Positioning Properties
|
||||
|
||||
Just **DON'T DO THIS**.
|
||||
Just**DON'T DO THIS**.
|
||||
|
||||
**IT IS DANGEROUS** to bind one positining properties to another. For example, you may want to keep a composition takes exactly the left half of its parent composition. But if you bind **AlignmentToParent** of this composition to its size, it could results in keeping growing its parent composition.
|
||||
**IT IS DANGEROUS**to bind one positining properties to another. For example, you may want to keep a composition takes exactly the left half of its parent composition. But if you bind**AlignmentToParent**of this composition to its size, it could results in keeping growing its parent composition.
|
||||
|
||||
When the parent composition grows (e.g. dragging the window), the child composition also grows because it wants to keep the gap exactly to **AlignmentToParent**. After that **AlignmentToParent** also grows because the child composition grows, and it makes the parent composition to grow again because the gap increases. This process never stops, the window will keep growing when it is resizing, until forever.
|
||||
When the parent composition grows (e.g. dragging the window), the child composition also grows because it wants to keep the gap exactly to**AlignmentToParent**. After that**AlignmentToParent**also grows because the child composition grows, and it makes the parent composition to grow again because the gap increases. This process never stops, the window will keep growing when it is resizing, until forever.
|
||||
|
||||
## Other Properties
|
||||
|
||||
### AssociatedControl
|
||||
|
||||
This property returns the control, whose **BoundsComposition** is this composition.
|
||||
This property returns the control, whose**BoundsComposition**is this composition.
|
||||
|
||||
This property could return **null** when this composition is not a **BoundsComposition** of a control.
|
||||
This property could return**null**when this composition is not a**BoundsComposition**of a control.
|
||||
|
||||
### RelatedControl
|
||||
|
||||
This property returns the most inner control that contains this composition.
|
||||
|
||||
This property could return **null** when this composition has not been put in a control yet.
|
||||
This property could return**null**when this composition has not been put in a control yet.
|
||||
|
||||
### RelatedControlHost
|
||||
|
||||
This property returns the window that contains this composition.
|
||||
|
||||
This property could return **null** when this composition has not been put in a control yet. Or the control has not been put in a window yet.
|
||||
This property could return**null**when this composition has not been put in a control yet. Or the control has not been put in a window yet.
|
||||
|
||||
## The timing of layout calculation
|
||||
|
||||
GacUI will trigger layout calculation automatically, once on each frame until calculation becomes table, and it stops.
|
||||
|
||||
It can also be triggered by calling the **ForceCalculateSizeImmediately** method on a composition you want to process. It calculates the layout of the composition and all its direct and indirect child compositions.
|
||||
It can also be triggered by calling the**ForceCalculateSizeImmediately**method on a composition you want to process. It calculates the layout of the composition and all its direct and indirect child compositions.
|
||||
|
||||
Only when the calculation is completed, the following properties of a composition are updated: - **CachedMinSize**, triggering the **CachedMinSizeChanged** property. - **CachedMinClientSize**, triggering the **CachedMinSizeChanged** property. - **CachedBounds**, triggering the **CachedBoundsChanged** property. - **CachedClientArea**, triggering the **CachedBoundsChanged** property.
|
||||
Only when the calculation is completed, the following properties of a composition are updated:
|
||||
- **CachedMinSize**, triggering the**CachedMinSizeChanged**property.
|
||||
- **CachedMinClientSize**, triggering the**CachedMinSizeChanged**property.
|
||||
- **CachedBounds**, triggering the**CachedBoundsChanged**property.
|
||||
- **CachedClientArea**, triggering the**CachedBoundsChanged**property.
|
||||
|
||||
### ForceCalculateSizeImmediately Method
|
||||
|
||||
@@ -122,7 +174,7 @@ The minimum size of a composition.
|
||||
|
||||
### CachedMinClientSize property
|
||||
|
||||
The minimum client size of a composition, which is **CachedMinSize** but the area of **InternalMargin** is excluded.
|
||||
The minimum client size of a composition, which is**CachedMinSize**but the area of**InternalMargin**is excluded.
|
||||
|
||||
### CachedBounds property
|
||||
|
||||
@@ -130,5 +182,5 @@ The position and actual size of a composition in its parent's coordinate space.
|
||||
|
||||
### CachedClientArea property
|
||||
|
||||
The position and actual size of a composition's client area in its parent's coordinate space, which is **CachedBounds** but the area of **InternalMargin** is excluded.
|
||||
The position and actual size of a composition's client area in its parent's coordinate space, which is**CachedBounds**but the area of**InternalMargin**is excluded.
|
||||
|
||||
|
||||
@@ -1,34 +1,44 @@
|
||||
# \<PartialView\>
|
||||
|
||||
**\<PartialView/\>** sticks its location and size to a ratio of the location and size of its parent composition.
|
||||
**\<PartialView/\>**sticks its location and size to a ratio of the location and size of its parent composition.
|
||||
|
||||
**\<PartialView/\>** is not a **\<Bounds/\>**, there is no writable **ExpectedBounds** and **AlignmentToParent** in this composition.
|
||||
**\<PartialView/\>**is not a**\<Bounds/\>**, there is no writable**ExpectedBounds**and**AlignmentToParent**in this composition.
|
||||
|
||||
**Margin** of this composition and **InternalMargin** of its parent composition are ignored.
|
||||
**Margin**of this composition and**InternalMargin**of its parent composition are ignored.
|
||||
|
||||
One of the scenario for **\<PartialView/\>** is the moving handle of a scroll bar.
|
||||
One of the scenario for**\<PartialView/\>**is the moving handle of a scroll bar.
|
||||
|
||||
## \<PartialView\>::WidthRatio and \<PartialView\>::WidthPageSize
|
||||
|
||||
The default value of **WidthRatio** is **0.0**.
|
||||
The default value of**WidthRatio**is**0.0**.
|
||||
|
||||
The default value of **WidthPageSize** is **1.0**.
|
||||
The default value of**WidthPageSize**is**1.0**.
|
||||
|
||||
- Value for **WidthRatio** should be in **[0, 1]** - Value for **WidthPageSize** should be in **[0, 1]** - **WidthRatio** + **WidthPageSize** should not exceed 1
|
||||
|
||||
These properties define the location and size of this composition in the following way: - The distance between this composition to the left border of its parent composition is **WidthRatio** * "width of its parent composition". - The width of this composition is **WidthPageSize** * "width of its parent composition".
|
||||
- Value for**WidthRatio**should be in**[0, 1]**
|
||||
- Value for**WidthPageSize**should be in**[0, 1]**
|
||||
- **WidthRatio**+**WidthPageSize**should not exceed 1
|
||||
|
||||
These properties define the location and size of this composition in the following way:
|
||||
- The distance between this composition to the left border of its parent composition is**WidthRatio*** "width of its parent composition".
|
||||
- The width of this composition is**WidthPageSize*** "width of its parent composition".
|
||||
|
||||
## \<PartialView\>::HeightRatio and \<PartialView\>::HeightPageSize
|
||||
|
||||
The default value of **HeightRatio** is **0.0**.
|
||||
The default value of**HeightRatio**is**0.0**.
|
||||
|
||||
The default value of **HeightPageSize** is **1.0**.
|
||||
The default value of**HeightPageSize**is**1.0**.
|
||||
|
||||
- Value for **HeightRatio** should be in **[0, 1]** - Value for **HeightPageSize** should be in **[0, 1]** - **HeightRatio** + **HeightPageSize** should not exceed 1
|
||||
|
||||
These properties define the location and size of this composition in the following way: - The distance between this composition to the left border of its parent composition is **HeightRatio** * "height of its parent composition". - The height of this composition is **HeightPageSize** * "height of its parent composition".
|
||||
- Value for**HeightRatio**should be in**[0, 1]**
|
||||
- Value for**HeightPageSize**should be in**[0, 1]**
|
||||
- **HeightRatio**+**HeightPageSize**should not exceed 1
|
||||
|
||||
These properties define the location and size of this composition in the following way:
|
||||
- The distance between this composition to the left border of its parent composition is**HeightRatio*** "height of its parent composition".
|
||||
- The height of this composition is**HeightPageSize*** "height of its parent composition".
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ dark skin control templates ](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml) .
|
||||
Please check out[dark skin control templates](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml).
|
||||
|
||||
|
||||
@@ -1,52 +1,63 @@
|
||||
# Repeat Compositions
|
||||
|
||||
**GuiRepeatCompositionBase** is the base class of all repeat compositions, which takes an item template and an item source, displays items in the item source using the item template, and maintain the order automatically when items in the item source are add/remove/change.
|
||||
**GuiRepeatCompositionBase**is the base class of all repeat compositions, which takes an item template and an item source, displays items in the item source using the item template, and maintain the order automatically when items in the item source are add/remove/change.
|
||||
|
||||
There are two kinds of repeat compositions: - **GuiNonVirtialRepeatCompositionBase**: Create and maintain instances of item template for all items. - [<RepeatStack/>](../../.././gacui/components/compositions/repeat_nonvirtual.md) - [<RepeatFlow/>](../../.././gacui/components/compositions/repeat_nonvirtual.md) - **GuiVirtialRepeatCompositionBase**: Create and maintain instances of item template for only visible items. Visible items mean items that are in the area of this composition, all items that are scrolled out will get their instance of item template released from the memory, and recreate when they are scrolled in again. - [<RepeatFreeHeightItem/>](../../.././gacui/components/compositions/repeat_virtual_freeheight.md) - [<RepeatFixedHeightItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedheight.md) - [<RepeatFixedHeightMultiColumnItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedheightmc.md) - [<RepeatFixedSizeMultiColumnItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedsizemc.md)
|
||||
There are two kinds of repeat compositions:
|
||||
- **GuiNonVirtialRepeatCompositionBase**: Create and maintain instances of item template for all items.
|
||||
- [<RepeatStack/>](../../.././gacui/components/compositions/repeat_nonvirtual.md)
|
||||
- [<RepeatFlow/>](../../.././gacui/components/compositions/repeat_nonvirtual.md)
|
||||
- **GuiVirtialRepeatCompositionBase**: Create and maintain instances of item template for only visible items. Visible items mean items that are in the area of this composition, all items that are scrolled out will get their instance of item template released from the memory, and recreate when they are scrolled in again.
|
||||
- [<RepeatFreeHeightItem/>](../../.././gacui/components/compositions/repeat_virtual_freeheight.md)
|
||||
- [<RepeatFixedHeightItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedheight.md)
|
||||
- [<RepeatFixedHeightMultiColumnItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedheightmc.md)
|
||||
- [<RepeatFixedSizeMultiColumnItem/>](../../.././gacui/components/compositions/repeat_virtual_fixedsizemc.md)
|
||||
|
||||
## ItemSource property
|
||||
|
||||
A valid object to assign to the **ItemSource** should be a **system::Enumerable^**. Here are built-in interfaces that inherits from **system::Enumerable**: - system::ReadonlyList - system::List - system::ObservableList
|
||||
A valid object to assign to the**ItemSource**should be a**system::Enumerable^**. Here are built-in interfaces that inherits from**system::Enumerable**:
|
||||
- system::ReadonlyList
|
||||
- system::List
|
||||
- system::ObservableList
|
||||
|
||||
In this page`missing document: /home/registered/vlppreflection.html` you could find C++ class names for these interfaces.
|
||||
Inthis page`missing document: /home/registered/vlppreflection.html`you could find C++ class names for these interfaces.
|
||||
|
||||
In [this page](../../.././workflow/lang/type.md) you could find **Workflow** syntax for these types.
|
||||
In[this page](../../.././workflow/lang/type.md)you could find**Workflow**syntax for these types.
|
||||
|
||||
Values in the collection must match **\<ref.Parameter/\>** of the [instance](../../.././gacui/xmlres/tag_instance.md) that is specified in the **ItemTemplate** property.
|
||||
Values in the collection must match**\<ref.Parameter/\>**of the[instance](../../.././gacui/xmlres/tag_instance.md)that is specified in the**ItemTemplate**property.
|
||||
|
||||
If there are [multiple instances](../../.././gacui/xmlres/instance/properties.md) in the **ItemTemplate** property, the first one whose **\<ref.Parameter/\>** is able to accept the value will be selected for the item in the collection. If none of them can, an exception will raise.
|
||||
If there are[multiple instances](../../.././gacui/xmlres/instance/properties.md)in the**ItemTemplate**property, the first one whose**\<ref.Parameter/\>**is able to accept the value will be selected for the item in the collection. If none of them can, an exception will raise.
|
||||
|
||||
To create a **system::Enumerable^** in C++, either call **vl::reflection::description::IValueEnumerable::Create**, or call **vl::reflection::description::BoxParameter** on an **vl::collections::IEnumerable\<T\>&**.
|
||||
To create a**system::Enumerable^**in C++, either call**vl::reflection::description::IValueEnumerable::Create**, or call**vl::reflection::description::BoxParameter**on an**vl::collections::IEnumerable\<T\>&**.
|
||||
|
||||
To create a **system::List^** in C++, either call **vl::reflection::description::IValueList::Create**, or call **vl::reflection::description::BoxParameter** on an **vl::collections::IList\<T\>&**.
|
||||
To create a**system::List^**in C++, either call**vl::reflection::description::IValueList::Create**, or call**vl::reflection::description::BoxParameter**on an**vl::collections::IList\<T\>&**.
|
||||
|
||||
The **BoxParameter** function creates a reference to the C++ collection, the C++ collection and the created object share items in the collection, and one can observe changes from another.
|
||||
The**BoxParameter**function creates a reference to the C++ collection, the C++ collection and the created object share items in the collection, and one can observe changes from another.
|
||||
|
||||
## Binding system::ObservableList to ItemSource property
|
||||
|
||||
If an **ObservableList** is assigned to the **ItemSource** property, when items in the list changed, associated instance of item templates will be automatically created or destroyed.
|
||||
If an**ObservableList**is assigned to the**ItemSource**property, when items in the list changed, associated instance of item templates will be automatically created or destroyed.
|
||||
|
||||
To create a **system::ObservableList^** in C++, either call **vl::reflection::description::IValueObservableList::Create**, or use **vl::collections::ObservableList\<T\>** as your collection class and call the **BoxParameter** function on it.
|
||||
To create a**system::ObservableList^**in C++, either call**vl::reflection::description::IValueObservableList::Create**, or use**vl::collections::ObservableList\<T\>**as your collection class and call the**BoxParameter**function on it.
|
||||
|
||||
The **BoxParameter** function creates a reference to the C++ collection, the C++ collection and the created object share items in the collection, and one can observe changes from another.
|
||||
The**BoxParameter**function creates a reference to the C++ collection, the C++ collection and the created object share items in the collection, and one can observe changes from another.
|
||||
|
||||
## ItemTemplate property
|
||||
|
||||
The [ItemTemplate](../../.././gacui/xmlres/instance/properties.md) property accepts one or a list of [instances](../../.././gacui/xmlres/tag_instance.md) in their full names or XML names.
|
||||
The[ItemTemplate](../../.././gacui/xmlres/instance/properties.md)property accepts one or a list of[instances](../../.././gacui/xmlres/tag_instance.md)in their full names or XML names.
|
||||
|
||||
Instances here are required to have exactly one **\<ref.Parameter/\>** as the only argument in their constructor.
|
||||
Instances here are required to have exactly one**\<ref.Parameter/\>**as the only argument in their constructor.
|
||||
|
||||
When **ItemSource** is being assigned, or when **ItemSource** is a **system::ObservableList^** and new items are inserted to the list, instances in **ItemTemplate** will be tested one by one to see if its constructor argument could accept the item in the list.
|
||||
When**ItemSource**is being assigned, or when**ItemSource**is a**system::ObservableList^**and new items are inserted to the list, instances in**ItemTemplate**will be tested one by one to see if its constructor argument could accept the item in the list.
|
||||
|
||||
The first instance of a successful test will be created with the item in the list, with **MinSizeLimitation** set to **LimitToElementAndChildren** and **Margin** set to **left:0 top:0 right:0 bottom:0**.
|
||||
The first instance of a successful test will be created with the item in the list, with**MinSizeLimitation**set to**LimitToElementAndChildren**and**Margin**set to**left:0 top:0 right:0 bottom:0**.
|
||||
|
||||
## Context property
|
||||
|
||||
**Context** property of any living **ItemTemplate** instance will always sync to **Context** property of the repeat composition.
|
||||
**Context**property of any living**ItemTemplate**instance will always sync to**Context**property of the repeat composition.
|
||||
|
||||
**\<RepeatStack/\>** and **\<RepeatFlow/\>** are **\<Stack/\>** and **\<Flow/\>** with data binding.
|
||||
**\<RepeatStack/\>**and**\<RepeatFlow/\>**are**\<Stack/\>**and**\<Flow/\>**with data binding.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ the demo for <RepeatStack/> and <RepeatFlow/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatTabPage.xml) and its [ sample item templates ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatComponents.xml) .
|
||||
Please check out[the demo for <RepeatStack/> and <RepeatFlow/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatTabPage.xml)and its[sample item templates](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatComponents.xml).
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# \<RepeatStack\> and \<RepeatFlow\>
|
||||
|
||||
**\<RepeatStack/\>** and **\<RepeatFlow/\>** are **\<Stack/\>** and **\<Flow/\>** with data binding.
|
||||
**\<RepeatStack/\>**and**\<RepeatFlow/\>**are**\<Stack/\>**and**\<Flow/\>**with data binding.
|
||||
|
||||
You are not required to create **\<StackItem/\>** or **\<FlowItem/\>** for each item. Instead, you bind a collection object to the **ItemSource** property, assign an item template to the **ItemTemplate** property, **\<RepeatStack/\>** or **\<RepeatFlow/\>** will create **\<StackItem/\>** or **\<FlowItem/\>** for each item in **ItemSource**, each containing an instance from **ItemTemplate** to display an item in **ItemSource**.
|
||||
You are not required to create**\<StackItem/\>**or**\<FlowItem/\>**for each item. Instead, you bind a collection object to the**ItemSource**property, assign an item template to the**ItemTemplate**property,**\<RepeatStack/\>**or**\<RepeatFlow/\>**will create**\<StackItem/\>**or**\<FlowItem/\>**for each item in**ItemSource**, each containing an instance from**ItemTemplate**to display an item in**ItemSource**.
|
||||
|
||||
**\<RepeatStack/\>** inherits from **\<Stack/\>**, **\<RepeatFlow/\>** inherits from **\<Flow/\>**, all properties in **\<Stack/\>** or **\<Flow/\>** are available.
|
||||
**\<RepeatStack/\>**inherits from**\<Stack/\>**,**\<RepeatFlow/\>**inherits from**\<Flow/\>**, all properties in**\<Stack/\>**or**\<Flow/\>**are available.
|
||||
|
||||
## Accessing auto-managed \<StackItem/\> or \<FlowItem/\>
|
||||
|
||||
**\<RepeatStack/\>::StackItems** property or **\<RepeatFlow/\>::FlowItems** property contains the same number of **\<StackItem/\>** or **\<FlowItem/\>** to items in **ItemSource** in exactly the same order.
|
||||
**\<RepeatStack/\>::StackItems**property or**\<RepeatFlow/\>::FlowItems**property contains the same number of**\<StackItem/\>**or**\<FlowItem/\>**to items in**ItemSource**in exactly the same order.
|
||||
|
||||
If a **system::ObservableList^** is assigned to **ItemSource**, the items and the order will be kept throught out the running time. Otherwise these compositions only reflect items in the collection at the moment of assigning to **ItemSource**.
|
||||
If a**system::ObservableList^**is assigned to**ItemSource**, the items and the order will be kept throught out the running time. Otherwise these compositions only reflect items in the collection at the moment of assigning to**ItemSource**.
|
||||
|
||||
Each **\<StackItem/\>** or **\<FlowItem/\>** has an only child composition which is an selected instance from **ItemTemplate**.
|
||||
Each**\<StackItem/\>**or**\<FlowItem/\>**has an only child composition which is an selected instance from**ItemTemplate**.
|
||||
|
||||
To access the item template instance of a specified item in **ItemSource**, just use **StackItems** or **FlowItems** with the same index, and find the first direct child composition of the returned **\<StackItem/\>** or **\<FlowItem/\>**.
|
||||
To access the item template instance of a specified item in**ItemSource**, just use**StackItems**or**FlowItems**with the same index, and find the first direct child composition of the returned**\<StackItem/\>**or**\<FlowItem/\>**.
|
||||
|
||||
To access **\<StackItem/\>** or **\<FlowItem/\>** inside the item template instance, just find its direct parent composition.
|
||||
To access**\<StackItem/\>**or**\<FlowItem/\>**inside the item template instance, just find its direct parent composition.
|
||||
|
||||
When **null** is assigned to **ItemSource**, all items will be deleted.
|
||||
When**null**is assigned to**ItemSource**, all items will be deleted.
|
||||
|
||||
|
||||
@@ -1,46 +1,49 @@
|
||||
# Virtual Repeat Compositions
|
||||
|
||||
**GuiVirtualRepeatCompositionBase** maintain instances of item template automatically to render items in the item source.
|
||||
**GuiVirtualRepeatCompositionBase**maintain instances of item template automatically to render items in the item source.
|
||||
|
||||
## Axis property
|
||||
|
||||
All repeat compositions maintain items in a default order. To change the order, set a new axis to the **Axis** property. **Axis** in **GuiVirtualRepeatCompositionBase** is very similar to [Axis in <Flow/>](../../.././gacui/components/compositions/flow.md).
|
||||
All repeat compositions maintain items in a default order. To change the order, set a new axis to the**Axis**property.**Axis**in**GuiVirtualRepeatCompositionBase**is very similar to[Axis in <Flow/>](../../.././gacui/components/compositions/flow.md).
|
||||
|
||||
## UseMinimumTotalSize property
|
||||
|
||||
The default value is **false**.
|
||||
The default value is**false**.
|
||||
|
||||
When **UseMinimumTotalSize** is **true**, **TotalSize** returns a smallest size but large enough to make scrolling right.
|
||||
When**UseMinimumTotalSize**is**true**,**TotalSize**returns a smallest size but large enough to make scrolling right.
|
||||
|
||||
For example, in **\<RepeatFixedHeightItem/\>**, The width of **TotalSize** becomes **0** when **UseMinimumTotalSize** is **true** and **ItemWidth** is **-1**. Because under such configuration, widths of items always equal to the width of **\<RepeatFixedHeightItem/\>** itself, it provides no information to control the scrolling, and it is very useful to make the horizontal scroll disappear forever.
|
||||
For example, in**\<RepeatFixedHeightItem/\>**, The width of**TotalSize**becomes**0**when**UseMinimumTotalSize**is**true**and**ItemWidth**is**-1**. Because under such configuration, widths of items always equal to the width of**\<RepeatFixedHeightItem/\>**itself, it provides no information to control the scrolling, and it is very useful to make the horizontal scroll disappear forever.
|
||||
|
||||
But the height of **TotalSize** is not affected, the value is necessary to control the scrolling.
|
||||
But the height of**TotalSize**is not affected, the value is necessary to control the scrolling.
|
||||
|
||||
**NOTE**: Scroll bars are not part of this composition, instead the following properties could be combined to configure scroll bars: - TotalSize - ViewLocation - Size of CachedBounds
|
||||
**NOTE**: Scroll bars are not part of this composition, instead the following properties could be combined to configure scroll bars:
|
||||
- TotalSize
|
||||
- ViewLocation
|
||||
- Size of CachedBounds
|
||||
|
||||
## TotalSize property
|
||||
|
||||
**TotalSize** property measures the area occupied by all items, regardless visible and non visible.
|
||||
**TotalSize**property measures the area occupied by all items, regardless visible and non visible.
|
||||
|
||||
## ViewLocation property
|
||||
|
||||
**ViewLocation** defines the left-top corner of the visible area in **TotalSize**. The size of the visible area is the size of this composition. Items that could render in this visible area becomes visible, otherwise invisible.
|
||||
**ViewLocation**defines the left-top corner of the visible area in**TotalSize**. The size of the visible area is the size of this composition. Items that could render in this visible area becomes visible, otherwise invisible.
|
||||
|
||||
## Accessing auto-managed instances of item template
|
||||
|
||||
**GuiVirtualRepeatCompositionBase** only creates instances of item template for only visible items. Visible items mean items that are in the area of this composition, all items that are scrolled out will get their instance of item template released from the memory, and recreate when they are scrolled in again.
|
||||
**GuiVirtualRepeatCompositionBase**only creates instances of item template for only visible items. Visible items mean items that are in the area of this composition, all items that are scrolled out will get their instance of item template released from the memory, and recreate when they are scrolled in again.
|
||||
|
||||
When an item is not visible, it is not able to find the instance of item template for this item.
|
||||
|
||||
If a **system::ObservableList^** is assigned to **ItemSource**, the items and the order will be kept throught out the running time. Otherwise these compositions only reflect items in the collection at the moment of assigning to **ItemSource**.
|
||||
If a**system::ObservableList^**is assigned to**ItemSource**, the items and the order will be kept throught out the running time. Otherwise these compositions only reflect items in the collection at the moment of assigning to**ItemSource**.
|
||||
|
||||
The **GetVisibleStyle** function gives you the instance of item template for an item. If the item is not visible, it returns **nullptr**.
|
||||
The**GetVisibleStyle**function gives you the instance of item template for an item. If the item is not visible, it returns**nullptr**.
|
||||
|
||||
The **GetVisibleIndex** function gives you the index of an item from an instance of item template. If it doesn't belong to this composition, it returns **-1**.
|
||||
The**GetVisibleIndex**function gives you the index of an item from an instance of item template. If it doesn't belong to this composition, it returns**-1**.
|
||||
|
||||
The **FindItemByRealKeyDirection** and **FindItemByVirtualKeyDirection** function find an item that is related to the specified item using a key. **VirtualKey** uses the logical order of the composition. **RealKey** uses the render order of the composition. When **Axis** is unchanged or set using an instance of **GuiDefaultAxis**, they are identical.
|
||||
The**FindItemByRealKeyDirection**and**FindItemByVirtualKeyDirection**function find an item that is related to the specified item using a key.**VirtualKey**uses the logical order of the composition.**RealKey**uses the render order of the composition. When**Axis**is unchanged or set using an instance of**GuiDefaultAxis**, they are identical.
|
||||
|
||||
The **EnsureItemVisible** function tries its best to update **ViewLocation** to make the specified item visible.
|
||||
The**EnsureItemVisible**function tries its best to update**ViewLocation**to make the specified item visible.
|
||||
|
||||
When **null** is assigned to **ItemSource**, all items will be deleted.
|
||||
When**null**is assigned to**ItemSource**, all items will be deleted.
|
||||
|
||||
|
||||
+4
-4
@@ -4,13 +4,13 @@ This composition render items in a default order from top to bottom. All items h
|
||||
|
||||
## ItemWidth
|
||||
|
||||
The default value of this property is **-1**. When it is set to any non-negative number, it defines the width of all items.
|
||||
The default value of this property is**-1**. When it is set to any non-negative number, it defines the width of all items.
|
||||
|
||||
One of an example is the **Detail** view in **\<ListView\>**. When the size of the column bar is changed, item widths are changed.
|
||||
One of an example is the**Detail**view in**\<ListView\>**. When the size of the column bar is changed, item widths are changed.
|
||||
|
||||
## ItemYOffset
|
||||
|
||||
The default value of this property is **0**. When it is set to any positive number, it addes some space before the first item.
|
||||
The default value of this property is**0**. When it is set to any positive number, it addes some space before the first item.
|
||||
|
||||
One of an example is the **Detail** view in **\<ListView\>**. When the list is scrolled to the top, the first item is just below the column bar.
|
||||
One of an example is the**Detail**view in**\<ListView\>**. When the list is scrolled to the top, the first item is just below the column bar.
|
||||
|
||||
|
||||
@@ -1,36 +1,107 @@
|
||||
# Responsive Design Series
|
||||
|
||||
Responsive design compositions consist of following compositions: - **\<ResponsiveContainer/\>**: A composition that tells its **ResponsiveTarget** to switch to a different view when the size of the \<ResponsiveContainer/\> is changed. - **GuiResponsiveCompositionBase**: A composition that manages multiple views in order from large to small, it has following sub classes for different way of management: - **\<ResponsiveFixed/\>**: only has one level of view. - **\<ResponsiveView/\>**: allow manually assigned views: - **Views** accepts multiple **GuiResponsiveCompositionBase** in order from large to small as its levels of views. - **SharedControls** accepts multiple controls. When switching views, a **\<ResponsiveShared/\>** could move a referenced shared control from one view to another, keeping all its status (especially for editable controls). - **\<ResponsiveGroup/\>**: the number of its levels of views equals to one direct or indirect child **GuiResponsiveCompositionBase** that has the most levels of views. When it needs to switch to another view, it tells all direct or indirect child **GuiResponsiveCompositionBase** to synchronize to the same level of view. - **\<ResponsiveStack/\>**: the number of its levels of views equals to the sum of levels of views in all direct or indirect child **GuiResponsiveCompositionBase**. When it needs to switch to another view, it tells one indirect child **GuiResponsiveCompositionBase** to switch view, unless all has switched to its largest or the smallest views.
|
||||
Responsive design compositions consist of following compositions:
|
||||
- **\<ResponsiveContainer/\>**: A composition that tells its**ResponsiveTarget**to switch to a different view when the size of the \<ResponsiveContainer/\> is changed.
|
||||
- **GuiResponsiveCompositionBase**: A composition that manages multiple views in order from large to small, it has following sub classes for different way of management:
|
||||
- **\<ResponsiveFixed/\>**: only has one level of view.
|
||||
- **\<ResponsiveView/\>**: allow manually assigned views:
|
||||
- **Views**accepts multiple**GuiResponsiveCompositionBase**in order from large to small as its levels of views.
|
||||
- **SharedControls**accepts multiple controls. When switching views, a**\<ResponsiveShared/\>**could move a referenced shared control from one view to another, keeping all its status (especially for editable controls).
|
||||
- **\<ResponsiveGroup/\>**: the number of its levels of views equals to one direct or indirect child**GuiResponsiveCompositionBase**that has the most levels of views. When it needs to switch to another view, it tells all direct or indirect child**GuiResponsiveCompositionBase**to synchronize to the same level of view.
|
||||
- **\<ResponsiveStack/\>**: the number of its levels of views equals to the sum of levels of views in all direct or indirect child**GuiResponsiveCompositionBase**. When it needs to switch to another view, it tells one indirect child**GuiResponsiveCompositionBase**to switch view, unless all has switched to its largest or the smallest views.
|
||||
|
||||
Usually, a **\<ResponsiveContainer/\>** is put inside a window and configured to change its size according to the window size. And then use **\<ResponsiveView/\>**, **\<ResponsiveGroup/\>** and **\<ResponsiveStack/\>** together to control how controls are reorganized to fit in different sizes of the container. finally this **GuiResponsiveCompositionBase** tree will be assigned to **\<ResponsiveContainer/\>**::**ResponsiveTarget** to make the reorganizing automatically happens.
|
||||
Usually, a**\<ResponsiveContainer/\>**is put inside a window and configured to change its size according to the window size. And then use**\<ResponsiveView/\>**,**\<ResponsiveGroup/\>**and**\<ResponsiveStack/\>**together to control how controls are reorganized to fit in different sizes of the container. finally this**GuiResponsiveCompositionBase**tree will be assigned to**\<ResponsiveContainer/\>**::**ResponsiveTarget**to make the reorganizing automatically happens.
|
||||
|
||||
Typically, **\<ResponsiveFixed/\>** will only be put in **\<ResponsiveView/\>**::**Views** when this level of view doesn't have sub levels of views.
|
||||
Typically,**\<ResponsiveFixed/\>**will only be put in**\<ResponsiveView/\>**::**Views**when this level of view doesn't have sub levels of views.
|
||||
|
||||
## A responsive layout sample
|
||||
|
||||
- Source code: [Tutorial/GacUI_Layout/Responsive2/UI/Resource.xml](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Layout/Responsive2/UI/Resource.xml) - 
|
||||
|
||||
There are three level of views: - **View 1**: Buttons with icons and titles on the left side, and video icons on the right side. - **View 2**: Buttons with icons on the left side, and video icons on the right side. - **View 3**: Buttons in a menu on the top side, and video icons on the bottom side.
|
||||
- Source code:[Tutorial/GacUI_Layout/Responsive2/UI/Resource.xml](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Layout/Responsive2/UI/Resource.xml)
|
||||
- 
|
||||
|
||||
**View 1** is larger than **View 2** because titles of buttons are hidden.
|
||||
There are three level of views:
|
||||
- **View 1**: Buttons with icons and titles on the left side, and video icons on the right side.
|
||||
- **View 2**: Buttons with icons on the left side, and video icons on the right side.
|
||||
- **View 3**: Buttons in a menu on the top side, and video icons on the bottom side.
|
||||
|
||||
**View 2** is larger than **View 3** because buttons are hidden. Although the menu of **View 3** increases the height, but video icons are scrollable, the list control could shrink vertically to make spaces for the menu.
|
||||
**View 1**is larger than**View 2**because titles of buttons are hidden.
|
||||
|
||||
**View 2**is larger than**View 3**because buttons are hidden. Although the menu of**View 3**increases the height, but video icons are scrollable, the list control could shrink vertically to make spaces for the menu.
|
||||
|
||||
## A basic idea to implement this sample
|
||||
|
||||
We will easily find that, the difference between **View 1** and **View 2** is button titles. so the button template itself could be a **\<ResponsiveView/\>** which has two **\<ResponsiveFixed/\>** in its **Views** property: - The first (larger) view contains one icon and one title - The second (smaller) view contains only one icon
|
||||
We will easily find that, the difference between**View 1**and**View 2**is button titles. so the button template itself could be a**\<ResponsiveView/\>**which has two**\<ResponsiveFixed/\>**in its**Views**property:
|
||||
- The first (larger) view contains one icon and one title
|
||||
- The second (smaller) view contains only one icon
|
||||
|
||||
Now the button becomes responsive, you don't need to create two different view for **View 1** and **View 2** in **\<ResponsiveView/\>**, which is wasting memories and reducing performance. Instead, you could use a **\<ResponsiveGroup/\>** to contain these buttons. Since all buttons have 2 levels of views, so **\<ResponsiveGroup/\>** has 2 levels of views, because all child **GuiResponsiveCompositionBase** will synchronize to the same level of view.
|
||||
Now the button becomes responsive, you don't need to create two different view for**View 1**and**View 2**in**\<ResponsiveView/\>**, which is wasting memories and reducing performance. Instead, you could use a**\<ResponsiveGroup/\>**to contain these buttons. Since all buttons have 2 levels of views, so**\<ResponsiveGroup/\>**has 2 levels of views, because all child**GuiResponsiveCompositionBase**will synchronize to the same level of view.
|
||||
|
||||
Now **View 1** and **View 2** are represented in one **\<ResponsiveGroup/\>**, we have to create a **\<ResponsiveView/\>** to contain **\<ResponsiveGroup/\>** and **View 3** as its two views. **View 3** is contained in a **\<ResponsiveFixed/\>**, since all compositions in **\<ResponsiveView/\>**::**Views** must be **GuiResponsiveCompositionBase**.
|
||||
Now**View 1**and**View 2**are represented in one**\<ResponsiveGroup/\>**, we have to create a**\<ResponsiveView/\>**to contain**\<ResponsiveGroup/\>**and**View 3**as its two views.**View 3**is contained in a**\<ResponsiveFixed/\>**, since all compositions in**\<ResponsiveView/\>**::**Views**must be**GuiResponsiveCompositionBase**.
|
||||
|
||||
The list control for video icons could be registered in **\<ResponsiveView/\>**::**SharedControls**. When the application switches between views, the list control will be moved to different view, controlled by all **\<ResponsiveShared/\>** in each views.
|
||||
The list control for video icons could be registered in**\<ResponsiveView/\>**::**SharedControls**. When the application switches between views, the list control will be moved to different view, controlled by all**\<ResponsiveShared/\>**in each views.
|
||||
|
||||
Finally, the code looks like this (button templates are inlined, which is only for demo, not the way to implement): ``` <Window> <ResponsiveContainer AlignmentToParent="left:0 top:0 right:0 bottom:0"> <att.ResponsiveTarget> <ResponsiveView Direction="Horizontal"> <att.SharedControls> <ScrollContainer ref.Name="videoContainer" ... /> </att.SharedControls> <att.Views> <ResponsiveGroup Direction="Horizontal"> <!-- View 1 and View 2 --> ... <SelectableButtonTemplate> ... <ResponsiveView Direction="Horizontal"> <att.Views> <ResponsiveFixed> <!-- View 1: icon with title --> </ResponsiveFixed> <ResponsiveFixed> <!-- View 2: icon without title --> </ResponsiveFixed> </att.Views> </ResponsiveView> ... </SelectableButtonTemplate> <SelectableButtonTemplate .../> <SelectableButtonTemplate .../> <SelectableButtonTemplate .../> ... <!-- the place holder for videoContainer in View 1 and View 2 --> <ResponsiveShared Shared-ref="videoContainer"/> ... </ResponsiveGroup> <ResponsiveFixed> <!-- View 3 --> ... <ToolstripMenu .../> ... <!-- the place holder for videoContainer in View 3 --> <ResponsiveShared Shared-ref="videoContainer"/> ... </ResponsiveFixed> </att.Views> </ResponsiveView> </att.ResponsiveTarget> </ResponsiveContainer> </window> ``` - A shared control must appears in **\<ResponsiveView/\>**::**SharedControls** in order to be referenced by multiple **\<ResponsiveShared/\>**. - **Direction="Horizontal"** in the code means the composition responsives to changing of its width.
|
||||
Finally, the code looks like this (button templates are inlined, which is only for demo, not the way to implement):
|
||||
```
|
||||
<Window>
|
||||
<ResponsiveContainer AlignmentToParent="left:0 top:0 right:0 bottom:0">
|
||||
<att.ResponsiveTarget>
|
||||
<ResponsiveView Direction="Horizontal">
|
||||
<att.SharedControls>
|
||||
<ScrollContainer ref.Name="videoContainer" ... />
|
||||
</att.SharedControls>
|
||||
|
||||
The code organizes the **GuiResponsiveCompositionBase** as follows: - **\<ResponsiveView/\>** - View[0]: **\<ResponsiveGroup/\>** - **\<ResponsiveView/\>** - View [0]: **\<ResponsiveFixed/\>** (button with icon and title) - View [1]: **\<ResponsiveFixed/\>** (button with icon only) - ... - View[1]: **\<ResponsiveFixed/\>** (button in menu)
|
||||
<att.Views>
|
||||
<ResponsiveGroup Direction="Horizontal">
|
||||
<!-- View 1 and View 2 -->
|
||||
...
|
||||
<SelectableButtonTemplate>
|
||||
...
|
||||
<ResponsiveView Direction="Horizontal">
|
||||
<att.Views>
|
||||
<ResponsiveFixed> <!-- View 1: icon with title --> </ResponsiveFixed>
|
||||
<ResponsiveFixed> <!-- View 2: icon without title --> </ResponsiveFixed>
|
||||
</att.Views>
|
||||
</ResponsiveView>
|
||||
...
|
||||
</SelectableButtonTemplate>
|
||||
<SelectableButtonTemplate .../>
|
||||
<SelectableButtonTemplate .../>
|
||||
<SelectableButtonTemplate .../>
|
||||
...
|
||||
<!-- the place holder for videoContainer in View 1 and View 2 -->
|
||||
<ResponsiveShared Shared-ref="videoContainer"/>
|
||||
...
|
||||
</ResponsiveGroup>
|
||||
<ResponsiveFixed>
|
||||
<!-- View 3 -->
|
||||
...
|
||||
<ToolstripMenu .../>
|
||||
...
|
||||
<!-- the place holder for videoContainer in View 3 -->
|
||||
<ResponsiveShared Shared-ref="videoContainer"/>
|
||||
...
|
||||
</ResponsiveFixed>
|
||||
</att.Views>
|
||||
</ResponsiveView>
|
||||
</att.ResponsiveTarget>
|
||||
</ResponsiveContainer>
|
||||
</window>
|
||||
```
|
||||
|
||||
When the window is getting smaller, **\<ResponsiveGroup/\>** shrinks all buttons at the same time (because it is a group not a stack) to hide all button titles.
|
||||
- A shared control must appears in**\<ResponsiveView/\>**::**SharedControls**in order to be referenced by multiple**\<ResponsiveShared/\>**.
|
||||
- **Direction="Horizontal"**in the code means the composition responsives to changing of its width.
|
||||
|
||||
When the window is getting even smaller, **\<ResponsiveGroup/\>** cannot shrinks anymore, so the root **\<ResponsiveView/\>** switches to a second view in **\<ResponsiveFixed/\>** to move all button inside a menu on the top.
|
||||
The code organizes the**GuiResponsiveCompositionBase**as follows:
|
||||
- **\<ResponsiveView/\>**
|
||||
- View[0]:**\<ResponsiveGroup/\>**
|
||||
- **\<ResponsiveView/\>**
|
||||
- View [0]:**\<ResponsiveFixed/\>**(button with icon and title)
|
||||
- View [1]:**\<ResponsiveFixed/\>**(button with icon only)
|
||||
- ...
|
||||
- View[1]:**\<ResponsiveFixed/\>**(button in menu)
|
||||
|
||||
When the window is getting smaller,**\<ResponsiveGroup/\>**shrinks all buttons at the same time (because it is a group not a stack) to hide all button titles.
|
||||
|
||||
When the window is getting even smaller,**\<ResponsiveGroup/\>**cannot shrinks anymore, so the root**\<ResponsiveView/\>**switches to a second view in**\<ResponsiveFixed/\>**to move all button inside a menu on the top.
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# \<ResponsiveContainer\>
|
||||
|
||||
**\<ResponsiveContainer/\>** tells the associated **GuiResponsiveCompositionBase** to switch to another view when **Bounds** is changed.
|
||||
**\<ResponsiveContainer/\>**tells the associated**GuiResponsiveCompositionBase**to switch to another view when**Bounds**is changed.
|
||||
|
||||
## \<ResponsiveContainer\>::ResponsiveTarget
|
||||
|
||||
When a **GuiResponsiveCompositionBase** is assigned to **ResponsiveTarget**, it is also added as a child composition in \<ResponsiveContainer/\>, with its **AlignmentToParent** set to **left:0 top:0 right:0 bottom:0**, and it switches to the largest view that could fit in the **\<ResponsiveContainer/\>**.
|
||||
When a**GuiResponsiveCompositionBase**is assigned to**ResponsiveTarget**, it is also added as a child composition in \<ResponsiveContainer/\>, with its**AlignmentToParent**set to**left:0 top:0 right:0 bottom:0**, and it switches to the largest view that could fit in the**\<ResponsiveContainer/\>**.
|
||||
|
||||
When a **GuiResponsiveCompositionBase** is removed from **ResponsiveTarget**, it is also removed from \<ResponsiveContainer/\>.
|
||||
When a**GuiResponsiveCompositionBase**is removed from**ResponsiveTarget**, it is also removed from \<ResponsiveContainer/\>.
|
||||
|
||||
## Choosing a view
|
||||
|
||||
When a **\<ResponsiveContainer/\>** becomes larger, it will try to tell its **ResponsiveTarget** to switch to a largest view that could fit in the **\<ResponsiveContainer/\>**. If the current view is the largest view, or the next larger view could not fit in the **\<ResponsiveContainer/\>**, it stays with the current view.
|
||||
When a**\<ResponsiveContainer/\>**becomes larger, it will try to tell its**ResponsiveTarget**to switch to a largest view that could fit in the**\<ResponsiveContainer/\>**. If the current view is the largest view, or the next larger view could not fit in the**\<ResponsiveContainer/\>**, it stays with the current view.
|
||||
|
||||
When a **\<ResponsiveContainer/\>** becomes smaller, it does the same but try to switch to a smaller view.
|
||||
When a**\<ResponsiveContainer/\>**becomes smaller, it does the same but try to switch to a smaller view.
|
||||
|
||||
If the size of **\<ResponsiveContainer/\>** is decided by the window size, when the window is being resized, it takes effect only when the mouse is released. It doesn't change view when the mouse is still dragging.
|
||||
If the size of**\<ResponsiveContainer/\>**is decided by the window size, when the window is being resized, it takes effect only when the mouse is released. It doesn't change view when the mouse is still dragging.
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# \<ResponsiveFixed\>
|
||||
|
||||
**\<ResponsiveFixed/\>** only has one view. If there are some **GuiResponsiveCompositionBase** added as child compositions in **\<ResponsiveFixed/\>**, they are ignored and their views will not change.
|
||||
**\<ResponsiveFixed/\>**only has one view. If there are some**GuiResponsiveCompositionBase**added as child compositions in**\<ResponsiveFixed/\>**, they are ignored and their views will not change.
|
||||
|
||||
**\<ResponsiveFixed/\>** is a **GuiResponsiveCompositionBase** and a **\<Bounds/\>**.
|
||||
**\<ResponsiveFixed/\>**is a**GuiResponsiveCompositionBase**and a**\<Bounds/\>**.
|
||||
|
||||
Sometimes you want to just add a static view to **\<ResponsiveView/\>**::**View**, but **Views** requires **GuiResponsiveCompositionBase**. **\<ResponsiveFixed/\>** is designed for this scenario.
|
||||
Sometimes you want to just add a static view to**\<ResponsiveView/\>**::**View**, but**Views**requires**GuiResponsiveCompositionBase**.**\<ResponsiveFixed/\>**is designed for this scenario.
|
||||
|
||||
## \<ResponsiveFixed\>::Direction
|
||||
|
||||
Since **\<ResponsiveFixed/\>** only has one view, this property is ignored.
|
||||
Since**\<ResponsiveFixed/\>**only has one view, this property is ignored.
|
||||
|
||||
## \<ResponsiveFixed\>::LevelCount
|
||||
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
# \<ResponsiveGroup\>
|
||||
|
||||
**\<ResponsiveGroup/\>** tells its managed **GuiResponsiveCompositionBase** to switch view at the same time when itself is required to do so.
|
||||
**\<ResponsiveGroup/\>**tells its managed**GuiResponsiveCompositionBase**to switch view at the same time when itself is required to do so.
|
||||
|
||||
**\<ResponsiveGroup/\>** is a **GuiResponsiveCompositionBase** and a **\<Bounds/\>**.
|
||||
**\<ResponsiveGroup/\>**is a**GuiResponsiveCompositionBase**and a**\<Bounds/\>**.
|
||||
|
||||
## Managing child GuiResponsiveCompositionBase
|
||||
|
||||
When things inside a **\<ResponsiveGroup/\>** are changed, **\<ResponsiveGroup/\>** will search for any child composition that is a **GuiResponsiveCompositionBase**. If a child composition is not, it will search into this child composition and see if there are any **GuiResponsiveCompositionBase** recursively. When a **GuiResponsiveCompositionBase** is found, it stops searching for child compositions inside this **GuiResponsiveCompositionBase**.
|
||||
When things inside a**\<ResponsiveGroup/\>**are changed,**\<ResponsiveGroup/\>**will search for any child composition that is a**GuiResponsiveCompositionBase**. If a child composition is not, it will search into this child composition and see if there are any**GuiResponsiveCompositionBase**recursively. When a**GuiResponsiveCompositionBase**is found, it stops searching for child compositions inside this**GuiResponsiveCompositionBase**.
|
||||
|
||||
Eventually **\<ResponsiveGroup/\>** knows all child **GuiResponsiveCompositionBase** inside it.
|
||||
Eventually**\<ResponsiveGroup/\>**knows all child**GuiResponsiveCompositionBase**inside it.
|
||||
|
||||
**IMPORTANT**: If a child **GuiResponsiveCompositionBase** has a different **Direction** than **\<ResponsiveGroup/\>**, it is not a managed **GuiResponsiveCompositionBase**.
|
||||
**IMPORTANT**: If a child**GuiResponsiveCompositionBase**has a different**Direction**than**\<ResponsiveGroup/\>**, it is not a managed**GuiResponsiveCompositionBase**.
|
||||
|
||||
## \<ResponsiveGroup\>::Direction
|
||||
|
||||
The default value for this property is **Both**.
|
||||
The default value for this property is**Both**.
|
||||
|
||||
Valid values for this property are **Horizontal**, **Vertical** and **Both**.
|
||||
Valid values for this property are**Horizontal**,**Vertical**and**Both**.
|
||||
|
||||
When **Direction** is **Horizontal**, it only reacts to changing to its width. When **Direction** is **Vertical**, it only reacts to changing to its height.
|
||||
When**Direction**is**Horizontal**, it only reacts to changing to its width. When**Direction**is**Vertical**, it only reacts to changing to its height.
|
||||
|
||||
## \<ResponsiveGroup\>::LevelCount
|
||||
|
||||
This property represents how many different view it could have. It is the largest **LevelCount** of all managed **GuiResponsiveCompositionBase**.
|
||||
This property represents how many different view it could have. It is the largest**LevelCount**of all managed**GuiResponsiveCompositionBase**.
|
||||
|
||||
If there is no managed **GuiResponsiveCompositionBase**, **LevelCount** is 1.
|
||||
If there is no managed**GuiResponsiveCompositionBase**,**LevelCount**is 1.
|
||||
|
||||
## \<ResponsiveGroup\>::CurrentLevel
|
||||
|
||||
This property represents the current view of a **\<ResponsiveGroup/\>**.
|
||||
This property represents the current view of a**\<ResponsiveGroup/\>**.
|
||||
|
||||
The smallest view is 0, the largest view is **LevelCount** - 1.
|
||||
The smallest view is 0, the largest view is**LevelCount**- 1.
|
||||
|
||||
## Choosing a view
|
||||
|
||||
When a **\<ResponsiveGroup/\>** is required to switch to a larger view (increasing **CurrentLevel** by 1), or when a **\<ResponsiveGroup/\>** is required to switch to a smaller view (decreasing **CurrentLevel** by 1), it tells all managed **GuiResponsiveCompositionBase** to synchronize with that new **CurrentLevel**. If any **GuiResponsiveCompositionBase**'s **LevelCount** is not large enough, it stays with its largest view.
|
||||
When a**\<ResponsiveGroup/\>**is required to switch to a larger view (increasing**CurrentLevel**by 1), or when a**\<ResponsiveGroup/\>**is required to switch to a smaller view (decreasing**CurrentLevel**by 1), it tells all managed**GuiResponsiveCompositionBase**to synchronize with that new**CurrentLevel**. If any**GuiResponsiveCompositionBase**'s**LevelCount**is not large enough, it stays with its largest view.
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# \<ResponsiveShared\>
|
||||
|
||||
In **\<ResponsiveView/\>**, sometimes when it switch to a different view, the content is totaly changed by switching from one **GuiResponsiveCompositionBase** to another **GuiResponsiveCompositionBase** in **Views**. If a control with important status needs to be shared between different views, **\<ResponsiveShared/\>** could help.
|
||||
In**\<ResponsiveView/\>**, sometimes when it switch to a different view, the content is totaly changed by switching from one**GuiResponsiveCompositionBase**to another**GuiResponsiveCompositionBase**in**Views**. If a control with important status needs to be shared between different views,**\<ResponsiveShared/\>**could help.
|
||||
|
||||
This kind of scenarios are very common. For example, different views may share a text box. If different text box controls are used in different view to represent the same input data, users will be confused like the selected area is gone just because of changing the window size.
|
||||
|
||||
## \<ResponsiveView\>::SharedControls
|
||||
|
||||
All controls need to share between views must be created in the **SharedControls** collection property.
|
||||
All controls need to share between views must be created in the**SharedControls**collection property.
|
||||
|
||||
In order to make these controls being able to use in **\<ResponsiveShared/\>**, usually a control name needs to be specified in the [ref.Name](../../.././gacui/xmlres/tag_instance.md) attribute for each control.
|
||||
In order to make these controls being able to use in**\<ResponsiveShared/\>**, usually a control name needs to be specified in the[ref.Name](../../.././gacui/xmlres/tag_instance.md)attribute for each control.
|
||||
|
||||
When the **\<ResponsiveView/\>** is deleted, all controls in **SharedControls** will also be deleted.
|
||||
When the**\<ResponsiveView/\>**is deleted, all controls in**SharedControls**will also be deleted.
|
||||
|
||||
## \<ResponsiveShared\>::Shared
|
||||
|
||||
For any control that needs to appear in a specific location in a view, a **\<ResponsiveShared/\>** is used as a place holder. It is a **\<Bounds/\>** so all necessary properties are available just like a control's **BoundsComposition**.
|
||||
For any control that needs to appear in a specific location in a view, a**\<ResponsiveShared/\>**is used as a place holder. It is a**\<Bounds/\>**so all necessary properties are available just like a control's**BoundsComposition**.
|
||||
|
||||
In this composition, the control to appear is specified using the **Shared** property, usually using a [-ref](../../.././gacui/xmlres/instance/properties.md) binding.
|
||||
In this composition, the control to appear is specified using the**Shared**property, usually using a[-ref](../../.././gacui/xmlres/instance/properties.md)binding.
|
||||
|
||||
When a **GuiResponsiveCompositionBase** in **Views** is selected, all containing **\<ResponsiveShared/\>** in this composition will get a notice to make **Shared.BoundsComposition** become a child composition, with **Shared.BoundsComposition.AlignmentToParent** set to **left:0 top:0 right:0 bottom:0**. After that, all shared controls are moved to their place holders.
|
||||
When a**GuiResponsiveCompositionBase**in**Views**is selected, all containing**\<ResponsiveShared/\>**in this composition will get a notice to make**Shared.BoundsComposition**become a child composition, with**Shared.BoundsComposition.AlignmentToParent**set to**left:0 top:0 right:0 bottom:0**. After that, all shared controls are moved to their place holders.
|
||||
|
||||
|
||||
@@ -1,44 +1,50 @@
|
||||
# \<ResponsiveStack\>
|
||||
|
||||
**\<ResponsiveStack/\>** tells its managed **GuiResponsiveCompositionBase** to switch view one after another when itself is required to do so.
|
||||
**\<ResponsiveStack/\>**tells its managed**GuiResponsiveCompositionBase**to switch view one after another when itself is required to do so.
|
||||
|
||||
**\<ResponsiveStack/\>** is a **GuiResponsiveCompositionBase** and a **\<Bounds/\>**.
|
||||
**\<ResponsiveStack/\>**is a**GuiResponsiveCompositionBase**and a**\<Bounds/\>**.
|
||||
|
||||
## Managing child GuiResponsiveCompositionBase
|
||||
|
||||
When things inside a **\<ResponsiveStack/\>** are changed, **\<ResponsiveStack/\>** will search for any child composition that is a **GuiResponsiveCompositionBase**. If a child composition is not, it will search into this child composition and see if there are any **GuiResponsiveCompositionBase** recursively. When a **GuiResponsiveCompositionBase** is found, it stops searching for child compositions inside this **GuiResponsiveCompositionBase**.
|
||||
When things inside a**\<ResponsiveStack/\>**are changed,**\<ResponsiveStack/\>**will search for any child composition that is a**GuiResponsiveCompositionBase**. If a child composition is not, it will search into this child composition and see if there are any**GuiResponsiveCompositionBase**recursively. When a**GuiResponsiveCompositionBase**is found, it stops searching for child compositions inside this**GuiResponsiveCompositionBase**.
|
||||
|
||||
Eventually **\<ResponsiveStack/\>** knows all child **GuiResponsiveCompositionBase** inside it.
|
||||
Eventually**\<ResponsiveStack/\>**knows all child**GuiResponsiveCompositionBase**inside it.
|
||||
|
||||
**IMPORTANT**: If a child **GuiResponsiveCompositionBase** has a different **Direction** than **\<ResponsiveStack/\>**, it is not a managed **GuiResponsiveCompositionBase**.
|
||||
**IMPORTANT**: If a child**GuiResponsiveCompositionBase**has a different**Direction**than**\<ResponsiveStack/\>**, it is not a managed**GuiResponsiveCompositionBase**.
|
||||
|
||||
## \<ResponsiveStack\>::Direction
|
||||
|
||||
The default value for this property is **Both**.
|
||||
The default value for this property is**Both**.
|
||||
|
||||
Valid values for this property are **Horizontal**, **Vertical** and **Both**.
|
||||
Valid values for this property are**Horizontal**,**Vertical**and**Both**.
|
||||
|
||||
When **Direction** is **Horizontal**, it only reacts to changing to its width. When **Direction** is **Vertical**, it only reacts to changing to its height.
|
||||
When**Direction**is**Horizontal**, it only reacts to changing to its width. When**Direction**is**Vertical**, it only reacts to changing to its height.
|
||||
|
||||
## \<ResponsiveStack\>::LevelCount
|
||||
|
||||
This property represents how many different view it could have. It is "sum of **LevelCount** of all managed **GuiResponsiveCompositionBase**" - "the number of all managed **GuiResponsiveCompositionBase**" + 1.
|
||||
This property represents how many different view it could have. It is "sum of**LevelCount**of all managed**GuiResponsiveCompositionBase**" - "the number of all managed**GuiResponsiveCompositionBase**" + 1.
|
||||
|
||||
For example, there are 3 managed **GuiResponsiveCompositionBase**, their **LevelCount** are 2, 3 and 4: - **LevelCount** is 2 means that composition could change 1 times from smallest to largest. - **LevelCount** is 3 means that composition could change 2 times from smallest to largest. - **LevelCount** is 4 means that composition could change 3 times from smallest to largest. So in total this **\<ResponsiveStack/\>** could change 1 + 2 + 3 = 6 times from smallest to largest, its **LevelCount** must be 7, which is exactly "2 + 3 + 4 - 3(numbers of managed) + 1".
|
||||
For example, there are 3 managed**GuiResponsiveCompositionBase**, their**LevelCount**are 2, 3 and 4:
|
||||
- **LevelCount**is 2 means that composition could change 1 times from smallest to largest.
|
||||
- **LevelCount**is 3 means that composition could change 2 times from smallest to largest.
|
||||
- **LevelCount**is 4 means that composition could change 3 times from smallest to largest.So in total this**\<ResponsiveStack/\>**could change 1 + 2 + 3 = 6 times from smallest to largest, its**LevelCount**must be 7, which is exactly "2 + 3 + 4 - 3(numbers of managed) + 1".
|
||||
|
||||
If there is no managed **GuiResponsiveCompositionBase**, **LevelCount** is 1.
|
||||
If there is no managed**GuiResponsiveCompositionBase**,**LevelCount**is 1.
|
||||
|
||||
## \<ResponsiveStack\>::CurrentLevel
|
||||
|
||||
This property represents the current view of a **\<ResponsiveStack/\>**.
|
||||
This property represents the current view of a**\<ResponsiveStack/\>**.
|
||||
|
||||
The smallest view is 0, the largest view is **LevelCount** - 1.
|
||||
The smallest view is 0, the largest view is**LevelCount**- 1.
|
||||
|
||||
## Choosing a view
|
||||
|
||||
When a **\<ResponsiveStack/\>** is required to switch to a larger view (increasing **CurrentLevel** by 1), **\<ResponsiveStack/\>** will find a smallest managed **GuiResponsiveCompositionBase** in size to switch to a larger view. If it fails (usually because it has already switched to its largest view), then **\<ResponsiveStack/\>** will find the next smallest one, until one succeeded.
|
||||
When a**\<ResponsiveStack/\>**is required to switch to a larger view (increasing**CurrentLevel**by 1),**\<ResponsiveStack/\>**will find a smallest managed**GuiResponsiveCompositionBase**in size to switch to a larger view. If it fails (usually because it has already switched to its largest view), then**\<ResponsiveStack/\>**will find the next smallest one, until one succeeded.
|
||||
|
||||
When a **\<ResponsiveStack/\>** is required to switch to a smaller view (decreasing **CurrentLevel** by 1), **\<ResponsiveStack/\>** will find a largest managed **GuiResponsiveCompositionBase** in size to switch to a smaller view. If it fails (usually because it has already switched to its smallest view), then **\<ResponsiveStack/\>** will find the next largest one, until one succeeded.
|
||||
When a**\<ResponsiveStack/\>**is required to switch to a smaller view (decreasing**CurrentLevel**by 1),**\<ResponsiveStack/\>**will find a largest managed**GuiResponsiveCompositionBase**in size to switch to a smaller view. If it fails (usually because it has already switched to its smallest view), then**\<ResponsiveStack/\>**will find the next largest one, until one succeeded.
|
||||
|
||||
**\<ResponsiveStack/\>** measures the size of a **GuiResponsiveCompositionBase** according to **Direction**: - **Horizontal**: size equals to its width. - **Vertical**: size equals to its height. - **Both**: size equals to its area.
|
||||
**\<ResponsiveStack/\>**measures the size of a**GuiResponsiveCompositionBase**according to**Direction**:
|
||||
- **Horizontal**: size equals to its width.
|
||||
- **Vertical**: size equals to its height.
|
||||
- **Both**: size equals to its area.
|
||||
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
# \<ResponsiveView\>
|
||||
|
||||
**\<ResponsiveView/\>** tells its current managed **GuiResponsiveCompositionBase** to switch view, or switch to a new managed **GuiResponsiveCompositionBase**, when itself is required to do so.
|
||||
**\<ResponsiveView/\>**tells its current managed**GuiResponsiveCompositionBase**to switch view, or switch to a new managed**GuiResponsiveCompositionBase**, when itself is required to do so.
|
||||
|
||||
**\<ResponsiveView/\>** is a **GuiResponsiveCompositionBase** and a **\<Bounds/\>**.
|
||||
**\<ResponsiveView/\>**is a**GuiResponsiveCompositionBase**and a**\<Bounds/\>**.
|
||||
|
||||
## \<ResponsiveView\>::Views
|
||||
|
||||
**\<ResponsiveView/\>** only manages **GuiResponsiveCompositionBase** that is added to **Views**. The first one in **Views** is the one that is expected to be the largest one. The last one in **Views** is the one that is expected to be the smallest one.
|
||||
**\<ResponsiveView/\>**only manages**GuiResponsiveCompositionBase**that is added to**Views**. The first one in**Views**is the one that is expected to be the largest one. The last one in**Views**is the one that is expected to be the smallest one.
|
||||
|
||||
Although only the **CurrentView** is a child composition of **\<ResponsiveView/\>**, but every **GuiResponsiveCompositionBase** in **View** will be deleted when **\<ResponsiveView/\>** is deleted.
|
||||
Although only the**CurrentView**is a child composition of**\<ResponsiveView/\>**, but every**GuiResponsiveCompositionBase**in**View**will be deleted when**\<ResponsiveView/\>**is deleted.
|
||||
|
||||
**IMPORTANT**: If a **GuiResponsiveCompositionBase** in **View** has a different **Direction** than **\<ResponsiveView/\>**, its **LevelCount** will be treated like 1.
|
||||
**IMPORTANT**: If a**GuiResponsiveCompositionBase**in**View**has a different**Direction**than**\<ResponsiveView/\>**, its**LevelCount**will be treated like 1.
|
||||
|
||||
## \<ResponsiveView\>::Direction
|
||||
|
||||
The default value for this property is **Both**.
|
||||
The default value for this property is**Both**.
|
||||
|
||||
Valid values for this property are **Horizontal**, **Vertical** and **Both**.
|
||||
Valid values for this property are**Horizontal**,**Vertical**and**Both**.
|
||||
|
||||
When **Direction** is **Horizontal**, it only reacts to changing to its width. When **Direction** is **Vertical**, it only reacts to changing to its height.
|
||||
When**Direction**is**Horizontal**, it only reacts to changing to its width. When**Direction**is**Vertical**, it only reacts to changing to its height.
|
||||
|
||||
## \<ResponsiveView\>::LevelCount
|
||||
|
||||
This property represents how many different view it could have. It is the sum of **LevelCount** of all managed **GuiResponsiveCompositionBase**.
|
||||
This property represents how many different view it could have. It is the sum of**LevelCount**of all managed**GuiResponsiveCompositionBase**.
|
||||
|
||||
If there is no managed **GuiResponsiveCompositionBase**, **LevelCount** is 1.
|
||||
If there is no managed**GuiResponsiveCompositionBase**,**LevelCount**is 1.
|
||||
|
||||
## \<ResponsiveView\>::CurrentLevel
|
||||
|
||||
This property represents the current view of a **\<ResponsiveView/\>**.
|
||||
This property represents the current view of a**\<ResponsiveView/\>**.
|
||||
|
||||
The smallest view is 0, the largest view is **LevelCount** - 1.
|
||||
The smallest view is 0, the largest view is**LevelCount**- 1.
|
||||
|
||||
## \<ResponsiveView\>::CurrentView
|
||||
|
||||
Each view in **Views** could have multiple view (**LevelCount** \> 1). **CurrentView** represents a **GuiResponsiveCompositionBase** in **Views** who is selected to display one of its view.
|
||||
Each view in**Views**could have multiple view (**LevelCount**\> 1).**CurrentView**represents a**GuiResponsiveCompositionBase**in**Views**who is selected to display one of its view.
|
||||
|
||||
When **Views** is empty, **CurrentView** is **null**.
|
||||
When**Views**is empty,**CurrentView**is**null**.
|
||||
|
||||
**IMPORTANT**: **LevelCount IS NOT** always **Views.Count**, so **CurrentView IS NOT** always **Views[CurrentView]**.
|
||||
**IMPORTANT**:**LevelCount IS NOT**always**Views.Count**, so**CurrentView IS NOT**always**Views[CurrentView]**.
|
||||
|
||||
## Choosing a view
|
||||
|
||||
When a **\<ResponsiveView/\>** is required to switch to a larger view (increasing **CurrentLevel** by 1), **\<ResponsiveView/\>** will tell **CurrentView** to switch to a larger view. If **CurrentView** is already in its largest view, than **\<ResponsiveView/\>** switches **CurrentView** to its previous one in **Views**. The new **CurrentView** will be in its smallest view.
|
||||
When a**\<ResponsiveView/\>**is required to switch to a larger view (increasing**CurrentLevel**by 1),**\<ResponsiveView/\>**will tell**CurrentView**to switch to a larger view. If**CurrentView**is already in its largest view, than**\<ResponsiveView/\>**switches**CurrentView**to its previous one in**Views**. The new**CurrentView**will be in its smallest view.
|
||||
|
||||
When a **\<ResponsiveView/\>** is required to switch to a smaller view (decreasing **CurrentLevel** by 1), **\<ResponsiveView/\>** will tell **CurrentView** to switch to a smaller view. If **CurrentView** is already in its smallest view, than **\<ResponsiveView/\>** switches **CurrentView** to its next one in **Views**. The new **CurrentView** will be in its largest view.
|
||||
When a**\<ResponsiveView/\>**is required to switch to a smaller view (decreasing**CurrentLevel**by 1),**\<ResponsiveView/\>**will tell**CurrentView**to switch to a smaller view. If**CurrentView**is already in its smallest view, than**\<ResponsiveView/\>**switches**CurrentView**to its next one in**Views**. The new**CurrentView**will be in its largest view.
|
||||
|
||||
When **CurrentView** is changed, the old one is removed from **\<ResponsiveView/\>**, the new one is added as a child composition in **\<ResponsiveView/\>** with its **AlignmentToParent** set to **left:0 top:0 right:0 bottom:0**.
|
||||
When**CurrentView**is changed, the old one is removed from**\<ResponsiveView/\>**, the new one is added as a child composition in**\<ResponsiveView/\>**with its**AlignmentToParent**set to**left:0 top:0 right:0 bottom:0**.
|
||||
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
# \<SharedSizeRoot\> and \<SharedSizeItem\>
|
||||
|
||||
**\<SharedSizeRoot/\>** synchronizes **\<SharedSizeItem/\>** in it to have the same widths or heights.
|
||||
**\<SharedSizeRoot/\>**synchronizes**\<SharedSizeItem/\>**in it to have the same widths or heights.
|
||||
|
||||
**\<SharedSizeItem/\>** doesn't have to be a direct child of **\<SharedSizeRoot/\>**.
|
||||
**\<SharedSizeItem/\>**doesn't have to be a direct child of**\<SharedSizeRoot/\>**.
|
||||
|
||||
One of a useful secenario is to create control templates for menu items. **\<SharedSizeRoot/\>** is put in the container for menu items, **\<SharedSizeItem/\>** is put in the control template for each menu item. When menu items are added in the container, All **\<SharedSizeItem/\>** becomes (indirect) child compositions of the **\<SharedSizeRoot/\>**, and then widths for names and shortcut keys are synchronized.
|
||||
One of a useful secenario is to create control templates for menu items.**\<SharedSizeRoot/\>**is put in the container for menu items,**\<SharedSizeItem/\>**is put in the control template for each menu item. When menu items are added in the container, All**\<SharedSizeItem/\>**becomes (indirect) child compositions of the**\<SharedSizeRoot/\>**, and then widths for names and shortcut keys are synchronized.
|
||||
|
||||
This is why menu items are aligned like a table even when each pair of name and shortcut key are in separate controls.
|
||||
|
||||
## \<SharedSizeItem\>::Group
|
||||
|
||||
The default value is **an empty string**.
|
||||
The default value is**an empty string**.
|
||||
|
||||
Only **\<SharedSizeItem/\>** in the same **Group** synchronizes size between each other. Two **\<SharedSizeItem/\>** in different **Group** do not affect each other.
|
||||
Only**\<SharedSizeItem/\>**in the same**Group**synchronizes size between each other. Two**\<SharedSizeItem/\>**in different**Group**do not affect each other.
|
||||
|
||||
If this **\<SharedSizeItem/\>** is not a child composition of a **\<SharedSizeRoot/\>**, sizes are not synchronized with any others.
|
||||
If this**\<SharedSizeItem/\>**is not a child composition of a**\<SharedSizeRoot/\>**, sizes are not synchronized with any others.
|
||||
|
||||
If this **\<SharedSizeItem/\>** is a child composition of multiple **\<SharedSizeRoot/\>** and **\<SharedSizeItem/\>**, - If the nearest parent composition amnong them is a **\<SharedSizeItem/\>**, sizes are not synchronized with any others. - If the nearest parent composition amnong them is a **\<SharedSizeRoot/\>**, sizes are only synchronized with other valid **\<SharedSizeItem/\>** in this **\<SharedSizeRoot/\>**.
|
||||
If this**\<SharedSizeItem/\>**is a child composition of multiple**\<SharedSizeRoot/\>**and**\<SharedSizeItem/\>**,
|
||||
- If the nearest parent composition amnong them is a**\<SharedSizeItem/\>**, sizes are not synchronized with any others.
|
||||
- If the nearest parent composition amnong them is a**\<SharedSizeRoot/\>**, sizes are only synchronized with other valid**\<SharedSizeItem/\>**in this**\<SharedSizeRoot/\>**.
|
||||
|
||||
## \<SharedSizeItem\>::SharedWidth
|
||||
|
||||
The default value is **false**.
|
||||
The default value is**false**.
|
||||
|
||||
If **SharedWidth** is set to true, this **\<SharedSizeItem/\>** synchronizes its width with other **\<SharedSizeItem/\>** in the same **Group**.
|
||||
If**SharedWidth**is set to true, this**\<SharedSizeItem/\>**synchronizes its width with other**\<SharedSizeItem/\>**in the same**Group**.
|
||||
|
||||
## \<SharedSizeItem\>::SharedHeight
|
||||
|
||||
The default value is **false**.
|
||||
The default value is**false**.
|
||||
|
||||
If **SharedWidth** is set to true, this **\<SharedSizeItem/\>** synchronizes its height with other **\<SharedSizeItem/\>** in the same **Group**.
|
||||
If**SharedWidth**is set to true, this**\<SharedSizeItem/\>**synchronizes its height with other**\<SharedSizeItem/\>**in the same**Group**.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out the demo for [<SharedSizeRoot/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatTabPage.xml) and [<SharedSizeItem/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatComponents.xml) .
|
||||
Please check out the demo for[<SharedSizeRoot/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatTabPage.xml)and[<SharedSizeItem/>](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/RepeatComponents.xml).
|
||||
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
# \<SideAligned\>
|
||||
|
||||
**\<SideAligned/\>** sticks itself to a border of the parent composition.
|
||||
**\<SideAligned/\>**sticks itself to a border of the parent composition.
|
||||
|
||||
**\<SideAligned/\>** is not a **\<Bounds/\>**, there is no writable **ExpectedBounds** and **AlignmentToParent** in this composition.
|
||||
**\<SideAligned/\>**is not a**\<Bounds/\>**, there is no writable**ExpectedBounds**and**AlignmentToParent**in this composition.
|
||||
|
||||
**Margin** of this composition and **InternalMargin** of its parent composition are ignored.
|
||||
**Margin**of this composition and**InternalMargin**of its parent composition are ignored.
|
||||
|
||||
One of the scenario for **\<SideAligned/\>** is the arrow button of a scroll bar.
|
||||
One of the scenario for**\<SideAligned/\>**is the arrow button of a scroll bar.
|
||||
|
||||
## \<SlideAlign\>::Direction
|
||||
|
||||
The default value for **Direction** is **Top**. The following are valid values for this property: - **Left**: This makes the composition behaves like its **AlignmentToParent** is **left:0 top:0 right:-1 bottom:0**. Its width is decided by **MaxLength**, **MaxRatio** and the size of its parent composition. - **Top**: This makes the composition behaves like its **AlignmentToParent** is **left:0 top:0 right:0 bottom:-1**. Its height is decided by **MaxLength**, **MaxRatio** and the size of its parent composition. - **Right**: This makes the composition behaves like its **AlignmentToParent** is **left:-1 top:0 right:0 bottom:0**. Its width is decided by **MaxLength**, **MaxRatio** and the size of its parent composition. - **Bottom**: This makes the composition behaves like its **AlignmentToParent** is **left:0 top:-1 right:0 bottom:0**. Its height is decided by **MaxLength**, **MaxRatio** and the size of its parent composition.
|
||||
The default value for**Direction**is**Top**. The following are valid values for this property:
|
||||
- **Left**: This makes the composition behaves like its**AlignmentToParent**is**left:0 top:0 right:-1 bottom:0**. Its width is decided by**MaxLength**,**MaxRatio**and the size of its parent composition.
|
||||
- **Top**: This makes the composition behaves like its**AlignmentToParent**is**left:0 top:0 right:0 bottom:-1**. Its height is decided by**MaxLength**,**MaxRatio**and the size of its parent composition.
|
||||
- **Right**: This makes the composition behaves like its**AlignmentToParent**is**left:-1 top:0 right:0 bottom:0**. Its width is decided by**MaxLength**,**MaxRatio**and the size of its parent composition.
|
||||
- **Bottom**: This makes the composition behaves like its**AlignmentToParent**is**left:0 top:-1 right:0 bottom:0**. Its height is decided by**MaxLength**,**MaxRatio**and the size of its parent composition.
|
||||
|
||||
## \<SlideAlign\>::MaxLength and \<SlideAlign\>::MaxRatio
|
||||
|
||||
The default value for **MaxLength** is **10**.
|
||||
The default value for**MaxLength**is**10**.
|
||||
|
||||
The default value for **MaxRatio** is **1.0**. Value for this property should be in **[0, 1]**.
|
||||
The default value for**MaxRatio**is**1.0**. Value for this property should be in**[0, 1]**.
|
||||
|
||||
When **Direction** is **Left** or **Right**: - let X be **MaxLength**. - let Y be **MaxRatio** * "width of the parent composition". The width of this composition becomes **min(X, Y)**.
|
||||
When**Direction**is**Left**or**Right**:
|
||||
- let X be**MaxLength**.
|
||||
- let Y be**MaxRatio*** "width of the parent composition".The width of this composition becomes**min(X, Y)**.
|
||||
|
||||
When **Direction** is **Top** or **Bottom**: - let X be **MaxLength**. - let Y be **MaxRatio** * "height of the parent composition". The height of this composition becomes **min(X, Y)**.
|
||||
When**Direction**is**Top**or**Bottom**:
|
||||
- let X be**MaxLength**.
|
||||
- let Y be**MaxRatio*** "height of the parent composition".The height of this composition becomes**min(X, Y)**.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ dark skin control templates ](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml) .
|
||||
Please check out[dark skin control templates](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml).
|
||||
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
# \<Stack\> and \<StackItem\>
|
||||
|
||||
**\<Stack/\>** arrange all direct children **\<StackItem/\>** compositions in a line following the same direction.
|
||||
**\<Stack/\>**arrange all direct children**\<StackItem/\>**compositions in a line following the same direction.
|
||||
|
||||
If all **\<StackItem/\>** lines of horizontally, all of them share the same height. If all **\<StackItem/\>** lines of vertically, all of them share the same width.
|
||||
If all**\<StackItem/\>**lines of horizontally, all of them share the same height. If all**\<StackItem/\>**lines of vertically, all of them share the same width.
|
||||
|
||||
**\<StackItem/\>**::MinSizeLimitation is **LimitToElementAndChildren** by default.
|
||||
**\<StackItem/\>**::MinSizeLimitation is**LimitToElementAndChildren**by default.
|
||||
|
||||
## Properties
|
||||
|
||||
A few more properties are provided by **\<Stack/\>** and **\<StackItem/\>** to control the details of how to ordering **\<StackItem/\>**.
|
||||
A few more properties are provided by**\<Stack/\>**and**\<StackItem/\>**to control the details of how to ordering**\<StackItem/\>**.
|
||||
|
||||
**\<StackItem/\>** is not a **\<Bounds/\>**, there is no writable **ExpectedBounds** and **AlignmentToParent** in **\<StackItem/\>**.
|
||||
**\<StackItem/\>**is not a**\<Bounds/\>**, there is no writable**ExpectedBounds**and**AlignmentToParent**in**\<StackItem/\>**.
|
||||
|
||||
### \<Stack\>::Direction
|
||||
|
||||
The default value is **Horizontal**.
|
||||
The default value is**Horizontal**.
|
||||
|
||||
**Horizontal**, **ReversedHorizontal**, **Vertical** and **ReversedVertical** are all valid values for this property, deciding how **\<StackItem/\>** are line up in a **\<Stack/\>**.
|
||||
**Horizontal**,**ReversedHorizontal**,**Vertical**and**ReversedVertical**are all valid values for this property, deciding how**\<StackItem/\>**are line up in a**\<Stack/\>**.
|
||||
|
||||
### \<Stack\>::Padding
|
||||
|
||||
The default value is 0.
|
||||
|
||||
This property keeps an distance between each **\<StackItem/\>**.
|
||||
This property keeps an distance between each**\<StackItem/\>**.
|
||||
|
||||
### \<Stack\>::ExtraMargin
|
||||
|
||||
The default value is 0 for all its components.
|
||||
|
||||
This property keeps an distance between **\<Stack/\>** and **\<StackItem/\>**.
|
||||
This property keeps an distance between**\<Stack/\>**and**\<StackItem/\>**.
|
||||
|
||||
### \<StackItem\>::ExtraMargin
|
||||
|
||||
The default value is 0 for all its components.
|
||||
|
||||
This property adds a border to a **\<StackItem/\>**.
|
||||
This property adds a border to a**\<StackItem/\>**.
|
||||
|
||||
**IMPORTANT**: **ExtraMargin** does not affect how **other \<StackItem/\>** is positioned. Instead, after the position of a **\<StackItem/\>** is decided, **ExtraMargin** kicks in and add a border to enlarge it.
|
||||
**IMPORTANT**:**ExtraMargin**does not affect how**other \<StackItem/\>**is positioned. Instead, after the position of a**\<StackItem/\>**is decided,**ExtraMargin**kicks in and add a border to enlarge it.
|
||||
|
||||
Adding an **ExtraMargin** to a **\<StackItem/\>** does not increase the minimum size of its parent **\<Stack/\>**.
|
||||
Adding an**ExtraMargin**to a**\<StackItem/\>**does not increase the minimum size of its parent**\<Stack/\>**.
|
||||
|
||||
## Adding Stack Items
|
||||
|
||||
### \<Stack\>::Children()
|
||||
|
||||
When a new **\<StackItem/\>** is added to **\<Stack/\>** as a child, this **\<StackItem/\>** is always appended to the end of the line, regardless of its position in **\<Stack\>::Children**.
|
||||
When a new**\<StackItem/\>**is added to**\<Stack/\>**as a child, this**\<StackItem/\>**is always appended to the end of the line, regardless of its position in**\<Stack\>::Children**.
|
||||
|
||||
### \<Stack\>::InsertStackItem(index, item)
|
||||
|
||||
To control the position of a **\<StackItem/\>** in a line, call **\<Stack\>::InsertStackItem()** instead of **\<Stack\>::Children()**.
|
||||
To control the position of a**\<StackItem/\>**in a line, call**\<Stack\>::InsertStackItem()**instead of**\<Stack\>::Children()**.
|
||||
|
||||
This function also adds a **\<StackItem/\>** to the **\<Stack/\>**, but it allows the position of this **\<StackItem/\>** in a line to be specified, instead of adding it to the end of the line.
|
||||
This function also adds a**\<StackItem/\>**to the**\<Stack/\>**, but it allows the position of this**\<StackItem/\>**in a line to be specified, instead of adding it to the end of the line.
|
||||
|
||||
### \<Stack\>::GetStackItems()
|
||||
|
||||
Call this function to get all direct children **\<StackItem/\>** in the line order.
|
||||
Call this function to get all direct children**\<StackItem/\>**in the line order.
|
||||
|
||||
## Visibility of Stack Items
|
||||
|
||||
### \<Stack\>::IsStackItemClipped()
|
||||
|
||||
This function returns **false** when any part of any **\<StackItem/\>** is invisible or clipped by this **\<Stack/\>**.
|
||||
This function returns**false**when any part of any**\<StackItem/\>**is invisible or clipped by this**\<Stack/\>**.
|
||||
|
||||
### \<Stack\>::EnsureVisible(index)
|
||||
|
||||
When **MinSizeLimitation** of **\<Stack/\>** is not **LimitToElementAndChildren**, it is possible that some **\<StackItem/\>** are not visible because of the **\<Stack/\>** is too small.
|
||||
When**MinSizeLimitation**of**\<Stack/\>**is not**LimitToElementAndChildren**, it is possible that some**\<StackItem/\>**are not visible because of the**\<Stack/\>**is too small.
|
||||
|
||||
This function **"scrolls"** all items to make sure that the specified one is visible.
|
||||
This function**"scrolls"**all items to make sure that the specified one is visible.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Stack) .
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Stack).
|
||||
|
||||
|
||||
@@ -1,90 +1,124 @@
|
||||
# \<Table\>, \<Cell\>, \<RowSplitter\> and \<ColumnSplitter\>
|
||||
|
||||
**\<Table/\>** arrange all direct children **\<Cell/\>** compositions in a table with size configurations.
|
||||
**\<Table/\>**arrange all direct children**\<Cell/\>**compositions in a table with size configurations.
|
||||
|
||||
**\<Cell/\>**::MinSizeLimitation is **LimitToElementAndChildren** by default.
|
||||
**\<Cell/\>**::MinSizeLimitation is**LimitToElementAndChildren**by default.
|
||||
|
||||
## Properties
|
||||
|
||||
A few more properties are provided by **\<Table/\>** and **\<Cell/\>** to control the details of how to ordering **\<Cell/\>**.
|
||||
A few more properties are provided by**\<Table/\>**and**\<Cell/\>**to control the details of how to ordering**\<Cell/\>**.
|
||||
|
||||
**\<Cell/\>** is not a **\<Bounds/\>**, there is no writable **ExpectedBounds** and **AlignmentToParent** in **\<Cell/\>**.
|
||||
**\<Cell/\>**is not a**\<Bounds/\>**, there is no writable**ExpectedBounds**and**AlignmentToParent**in**\<Cell/\>**.
|
||||
|
||||
### \<Table\>::Rows and \<Table\>::Columns
|
||||
|
||||
They are collection properties that can only be used in GacUI XML Resource and Workflow. In order to access them in C++, please check out the following methods: - GetRows - GetRows - SetRowsAndColumns - GetRowOption - SetRowOption - GetColumnOption - SetColumnOption Call **SetRowsColumns** to allocate the numbers of rows and columns for this table, and then call **SetRowOption** and **SetColumnOption** to set the size configuration.
|
||||
They are collection properties that can only be used in GacUI XML Resource and Workflow. In order to access them in C++, please check out the following methods:
|
||||
- GetRows
|
||||
- GetRows
|
||||
- SetRowsAndColumns
|
||||
- GetRowOption
|
||||
- SetRowOption
|
||||
- GetColumnOption
|
||||
- SetColumnOptionCall**SetRowsColumns**to allocate the numbers of rows and columns for this table, and then call**SetRowOption**and**SetColumnOption**to set the size configuration.
|
||||
|
||||
In GacUI XML Resource, in order to have a 5x3 table, it is expected to have 5 values in **Rows** and 3 values in **Columns**.
|
||||
In GacUI XML Resource, in order to have a 5x3 table, it is expected to have 5 values in**Rows**and 3 values in**Columns**.
|
||||
|
||||
Values for these properties could be: - **composeType:MinSize**: the size of the cell is the minimum size for this composition. - **composeType:Absolute absolute:X**: the size of the cell cannot be smaller than X. X must be a non-negative integer. - **composeType:Percentage percentage:X**: the size of the cell is decided by all **Percentage** cells. X must be a non-negative number.
|
||||
Values for these properties could be:
|
||||
- **composeType:MinSize**: the size of the cell is the minimum size for this composition.
|
||||
- **composeType:Absolute absolute:X**: the size of the cell cannot be smaller than X. X must be a non-negative integer.
|
||||
- **composeType:Percentage percentage:X**: the size of the cell is decided by all**Percentage**cells. X must be a non-negative number.
|
||||
|
||||
Before repositioning cells, the table will collect all rows and cells that are **MinSize** and **Absolute**, spaces are first allocate to these rows and cells. And then if there are still spaces, spaces will be allocate to **Percentage** cells in proportion.
|
||||
Before repositioning cells, the table will collect all rows and cells that are**MinSize**and**Absolute**, spaces are first allocate to these rows and cells. And then if there are still spaces, spaces will be allocate to**Percentage**cells in proportion.
|
||||
|
||||
If **\<Table/\>**::MinSizeLimitation is set to **LimitToElementAndChildren**, the minimum size of the table is the sum of all cells' minimum sizes with paddings. For **Absolute** cells, if the absolute value is larger than its minimum size, the absolute value becomes the minimum size for this cell.
|
||||
If**\<Table/\>**::MinSizeLimitation is set to**LimitToElementAndChildren**, the minimum size of the table is the sum of all cells' minimum sizes with paddings. For**Absolute**cells, if the absolute value is larger than its minimum size, the absolute value becomes the minimum size for this cell.
|
||||
|
||||
The sum of all percentage values could be anything. for example, if a table has a 0 padding with these 5 row options: - **composeType:Percentage percentage:0.5** - **composeType:MinSize** - **composeType:Percentage percentage:1.0** - **composeType:Absolute absolute:200** - **composeType:Percentage percentage:0.5** and the minimum width for each cell is 100.
|
||||
The sum of all percentage values could be anything. for example, if a table has a 0 padding with these 5 row options:
|
||||
- **composeType:Percentage percentage:0.5**
|
||||
- **composeType:MinSize**
|
||||
- **composeType:Percentage percentage:1.0**
|
||||
- **composeType:Absolute absolute:200**
|
||||
- **composeType:Percentage percentage:0.5**and the minimum width for each cell is 100.
|
||||
|
||||
It is easy to know that the minimum width of this table is 500. If the table has a border and a cell padding of 10, its minimum width becomes 560.
|
||||
|
||||
In the space of 500: - 100 will be allocated to the 2nd cell - 200 will be allocated to the 4nd cell and there is still 200 left.
|
||||
In the space of 500:
|
||||
- 100 will be allocated to the 2nd cell
|
||||
- 200 will be allocated to the 4nd celland there is still 200 left.
|
||||
|
||||
The sum of all percentage values is 0.5 + 1.0 + 0.5 = 2. - The 1st cell will be allocated 50 (200 * 0.5 / 2) - The 3rd cell will be allocated 100 (200 * 1.0 / 2) - The 5th cell will be allocated 50 (200 * 0.5 / 2)
|
||||
The sum of all percentage values is 0.5 + 1.0 + 0.5 = 2.
|
||||
- The 1st cell will be allocated 50 (200 * 0.5 / 2)
|
||||
- The 3rd cell will be allocated 100 (200 * 1.0 / 2)
|
||||
- The 5th cell will be allocated 50 (200 * 0.5 / 2)
|
||||
|
||||
### \<Table\>::CellPadding
|
||||
|
||||
The default value is 0.
|
||||
|
||||
**CellPadding** keeps an distance between each **\<Cell/\>**.
|
||||
**CellPadding**keeps an distance between each**\<Cell/\>**.
|
||||
|
||||
### \<Table\>::BorderVisible
|
||||
|
||||
The default value is **true**.
|
||||
The default value is**true**.
|
||||
|
||||
If **BorderVisible** is true, cells are keep the distance of **CellPadding** to the border of the table, otherwise the distance is 0.
|
||||
If**BorderVisible**is true, cells are keep the distance of**CellPadding**to the border of the table, otherwise the distance is 0.
|
||||
|
||||
### \<Cell\>::Site
|
||||
|
||||
This is a required property in GacUI XML Resource.
|
||||
|
||||
This property can only be used in GacUI XML Resource and Workflow. In order to access them in C++, please check out the following methods: - GetRow - GetRowSpan - GetColumn - GetColumnSpan - SetSite**SetSite** requires 4 arguments, which are exactly the 4 components in this **Site** property.
|
||||
This property can only be used in GacUI XML Resource and Workflow. In order to access them in C++, please check out the following methods:
|
||||
- GetRow
|
||||
- GetRowSpan
|
||||
- GetColumn
|
||||
- GetColumnSpan
|
||||
- SetSite**SetSite**requires 4 arguments, which are exactly the 4 components in this**Site**property.
|
||||
|
||||
Value for this property is **row:R column:C rowSpan:RS columnSpan:CS**. The default values for **rowSpan** and **columnSpan** are 1. - **row**: specify the row where this cell locates starting from 0. - **column**: specify the column where this cell locates starting from 0. - **rowSpan**: specify how many rows does this cell take. - **columnSpan**: specify how many columns does this cell take.
|
||||
Value for this property is**row:R column:C rowSpan:RS columnSpan:CS**. The default values for**rowSpan**and**columnSpan**are 1.
|
||||
- **row**: specify the row where this cell locates starting from 0.
|
||||
- **column**: specify the column where this cell locates starting from 0.
|
||||
- **rowSpan**: specify how many rows does this cell take.
|
||||
- **columnSpan**: specify how many columns does this cell take.
|
||||
|
||||
A table is split to multiple cell blocks, a cell could take multiple cell blocks at once, but they must form a rectangle space. A cell block can only be taken by one cell.
|
||||
|
||||
**\<Cell/\>** are processed according to their order in GacUI XML Resource. If a cell is found to be taking cell blocks that have already been taken, the **Site** property of this cell is canceled, the position of this cell is undefined.
|
||||
**\<Cell/\>**are processed according to their order in GacUI XML Resource. If a cell is found to be taking cell blocks that have already been taken, the**Site**property of this cell is canceled, the position of this cell is undefined.
|
||||
|
||||
## Adding Cells in C++
|
||||
|
||||
To create a table in C++, these steps must be taken in order: - Call **SetRowsAndColumns** of the table to allocate cell blocks. - Call **SetRowOption** and **SetColumnOption** of the table for size configuration. - Call **SetSite** for cells to define which cell blocks are taken by each cell. - Add cells as a direct child composition of the table. - Call **UpdateCellBounds** of the table to tell that the configuration is ready.
|
||||
To create a table in C++, these steps must be taken in order:
|
||||
- Call**SetRowsAndColumns**of the table to allocate cell blocks.
|
||||
- Call**SetRowOption**and**SetColumnOption**of the table for size configuration.
|
||||
- Call**SetSite**for cells to define which cell blocks are taken by each cell.
|
||||
- Add cells as a direct child composition of the table.
|
||||
- Call**UpdateCellBounds**of the table to tell that the configuration is ready.
|
||||
|
||||
When contents of cells are changed, no action is required.
|
||||
|
||||
When size configurations are changed, or when cells are added or removed to the table, **UpdateCellBounds** must be called to tell the table to reorganize cells.
|
||||
When size configurations are changed, or when cells are added or removed to the table,**UpdateCellBounds**must be called to tell the table to reorganize cells.
|
||||
|
||||
## Adjusting Cells by Mouse
|
||||
|
||||
### \<RowSplitter\>
|
||||
|
||||
A **\<RowSplitter/\>** takes the space between two rows. This requires the table to have a non-zero **CellPadding**.
|
||||
A**\<RowSplitter/\>**takes the space between two rows. This requires the table to have a non-zero**CellPadding**.
|
||||
|
||||
One of a sibling row of the splitter is required to be **Absolute**.
|
||||
One of a sibling row of the splitter is required to be**Absolute**.
|
||||
|
||||
**RowsToTheTop** specifies how many rows are above this splitter. If the table has 5 rows, valid values for **RowsToTheTop** are 1 to 4.
|
||||
**RowsToTheTop**specifies how many rows are above this splitter. If the table has 5 rows, valid values for**RowsToTheTop**are 1 to 4.
|
||||
|
||||
After adding a splitter to the table, it can be dragged by a mouse to adjust the size of an **Absolute** row around the splitter.
|
||||
After adding a splitter to the table, it can be dragged by a mouse to adjust the size of an**Absolute**row around the splitter.
|
||||
|
||||
### \<ColumnSplitter\>
|
||||
|
||||
A **\<ColumnSplitter/\>** takes the space between two columns. This requires the table to have a non-zero **CellPadding**.
|
||||
A**\<ColumnSplitter/\>**takes the space between two columns. This requires the table to have a non-zero**CellPadding**.
|
||||
|
||||
One of a sibling column of the splitter is required to be **Absolute**.
|
||||
One of a sibling column of the splitter is required to be**Absolute**.
|
||||
|
||||
**ColumnsToTheLeft** specifies how many columns are above this splitter. If the table has 5 columns, valid values for **ColumnsToTheLeft** are 1 to 4.
|
||||
**ColumnsToTheLeft**specifies how many columns are above this splitter. If the table has 5 columns, valid values for**ColumnsToTheLeft**are 1 to 4.
|
||||
|
||||
After adding a splitter to the table, it can be dragged by a mouse to adjust the size of an **Absolute** column around the splitter.
|
||||
After adding a splitter to the table, it can be dragged by a mouse to adjust the size of an**Absolute**column around the splitter.
|
||||
|
||||
## Sample
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Table) .
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Layout/Table).
|
||||
|
||||
|
||||
@@ -1,38 +1,47 @@
|
||||
# \<Button\>
|
||||
|
||||
- **\<Button/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiButton* - **Template Tag**: \<ButtonTemplate/\> - **Template Name**: Button
|
||||
|
||||
**\<Button/\>** is a control for user to execute a command.
|
||||
- **\<Button/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiButton*
|
||||
- **Template Tag**: \<ButtonTemplate/\>
|
||||
- **Template Name**: Button
|
||||
|
||||
**\<Button/\>**is a control for user to execute a command.
|
||||
|
||||
## \<Button\> Properties
|
||||
|
||||
### ClickOnMouseUp
|
||||
|
||||
The default value for this property is **true**, but it could be different in sub classes.
|
||||
The default value for this property is**true**, but it could be different in sub classes.
|
||||
|
||||
When this property is **true**, **Clicked** raises when the mouse button is released. When this property is **false**, **Clicked** raises when the mouse button is pressed.
|
||||
When this property is**true**,**Clicked**raises when the mouse button is released. When this property is**false**,**Clicked**raises when the mouse button is pressed.
|
||||
|
||||
### AutoFocus
|
||||
|
||||
The default value for this property is **true**, but it could be different in sub classes.
|
||||
The default value for this property is**true**, but it could be different in sub classes.
|
||||
|
||||
When this property is **true**: - The button is focused when the mouse button is pressed. - The button is focused when it is executed by a **ALT** sequence. - The button accepts focus by **TAB**.
|
||||
When this property is**true**:
|
||||
- The button is focused when the mouse button is pressed.
|
||||
- The button is focused when it is executed by a**ALT**sequence.
|
||||
- The button accepts focus by**TAB**.
|
||||
|
||||
### IgnoreChildControlMouseEvents
|
||||
|
||||
The default value for this property is **true**, but it could be different in sub classes.
|
||||
The default value for this property is**true**, but it could be different in sub classes.
|
||||
|
||||
When mouse operations happen in child controls which are contained in a button, the button ignores these operations so that it behaves like not being clicked. But once the **IgnoreChildControlMouseEvents** property is set to **false**, this behavior changes.
|
||||
When mouse operations happen in child controls which are contained in a button, the button ignores these operations so that it behaves like not being clicked. But once the**IgnoreChildControlMouseEvents**property is set to**false**, this behavior changes.
|
||||
|
||||
This property is very useful when adding child controls for visual effect only.
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_button](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_button/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_button](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_button/Resource.xml)
|
||||
- 
|
||||
|
||||
## \<Button\> Events
|
||||
|
||||
### Clicked
|
||||
|
||||
This event raises when it is clicked, or it is activated by a **ALT** sequence.
|
||||
This event raises when it is clicked, or it is activated by a**ALT**sequence.
|
||||
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
# \<CustomControl\>
|
||||
|
||||
- **\<CustomControl/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiCustomControl* - **Template Tag**: \<ControlTemplate/\> - **Template Name**: CustomControl
|
||||
|
||||
**\<CustomControl/\>** is a control for making new controls in GacUI XML Resource. ``` <Instance ref.CodeBehind="false" ref.Class="demo::MyControl> <CustomControl/> </Instance> ``` **\<CustomControl/\>** is usually a base class of an [ <Instance> ](../../../.././gacui/xmlres/tag_instance.md). Here we create a class **demo::MyControl** inheriting from **\<CustomControl/\>**.
|
||||
- **\<CustomControl/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiCustomControl*
|
||||
- **Template Tag**: \<ControlTemplate/\>
|
||||
- **Template Name**: CustomControl
|
||||
|
||||
To add new properties and other members to the new control, just define them in **Workflow** and put all of them in [<ref.Members/>](../../../.././gacui/xmlres/tag_instance.md).
|
||||
**\<CustomControl/\>**is a control for making new controls in GacUI XML Resource.
|
||||
```
|
||||
<Instance ref.CodeBehind="false" ref.Class="demo::MyControl>
|
||||
<CustomControl/>
|
||||
</Instance>
|
||||
```
|
||||
**\<CustomControl/\>**is usually a base class of an[<Instance>](../../../.././gacui/xmlres/tag_instance.md). Here we create a class**demo::MyControl**inheriting from**\<CustomControl/\>**.
|
||||
|
||||
To make such control focusable, use the **FocusableComposition** to specify a composition to receive keyboard and other related events.
|
||||
To add new properties and other members to the new control, just define them in**Workflow**and put all of them in[<ref.Members/>](../../../.././gacui/xmlres/tag_instance.md).
|
||||
|
||||
To make such control focusable, use the**FocusableComposition**to specify a composition to receive keyboard and other related events.
|
||||
|
||||
## Adding something to a custom control
|
||||
|
||||
**\<CustomControl/\>** is just a control. Compositions and controls in the window will be added to its **ContainerComposition**. You don't have to explicitly use **att.ContainerComposition**.
|
||||
**\<CustomControl/\>**is just a control. Compositions and controls in the window will be added to its**ContainerComposition**. You don't have to explicitly use**att.ContainerComposition**.
|
||||
|
||||
As a **GuiInstanceRootObject**, components can also be added to a window.
|
||||
As a**GuiInstanceRootObject**, components can also be added to a window.
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/TriplePhaseImageButton) for details.
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/TriplePhaseImageButton)for details.
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# \<DateComboBox\>
|
||||
|
||||
- **\<DateComboBox/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiDateComboBox* - **Template Tag**: \<DateComboBoxTemplate/\> - **Template Name**: DateComboBox
|
||||
|
||||
**\<DateComboBox/\>** is a combo box control with a **\<DatePicker/\>** in the dropdown container.
|
||||
- **\<DateComboBox/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiDateComboBox*
|
||||
- **Template Tag**: \<DateComboBoxTemplate/\>
|
||||
- **Template Name**: DateComboBox
|
||||
|
||||
**\<DateComboBox/\>**is a combo box control with a**\<DatePicker/\>**in the dropdown container.
|
||||
|
||||
## \<DateComboBox\> Properties
|
||||
|
||||
@@ -10,13 +14,15 @@
|
||||
|
||||
The default value is the today provided by the OS.
|
||||
|
||||
When a day is selected from the **\<DatePicker/\>** in the dropdown container, **SelectedDate** and **Text** will be updated,
|
||||
When a day is selected from the**\<DatePicker/\>**in the dropdown container,**SelectedDate**and**Text**will be updated,
|
||||
|
||||
### DatePicker
|
||||
|
||||
The **\<DatePicker/\>** control in the dropdown container.
|
||||
The**\<DatePicker/\>**control in the dropdown container.
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_datecombo](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_datecombo/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_datecombo](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_datecombo/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# \<DatePicker\>
|
||||
|
||||
- **\<DatePicker/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiDatePicker* - **Template Tag**: \<DatePickerTemplate/\> - **Template Name**: DatePicker
|
||||
|
||||
**\<DatePicker/\>** is a control that looks like a calendar. In the default control templates, year and month can be chosen in two combo box controls. When a specific month is selected, a calender will display days in their correct positions.
|
||||
- **\<DatePicker/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiDatePicker*
|
||||
- **Template Tag**: \<DatePickerTemplate/\>
|
||||
- **Template Name**: DatePicker
|
||||
|
||||
A calendar-like control template is not easy to implement in GacUI XML Resource for **\<DatePicker/\>**, so **\<CommonDatePickerLook/\>** is provided for writing such control templates. Please check out [ the default control templates ](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Misc.xml) for details.
|
||||
**\<DatePicker/\>**is a control that looks like a calendar. In the default control templates, year and month can be chosen in two combo box controls. When a specific month is selected, a calender will display days in their correct positions.
|
||||
|
||||
A calendar-like control template is not easy to implement in GacUI XML Resource for**\<DatePicker/\>**, so**\<CommonDatePickerLook/\>**is provided for writing such control templates. Please check out[the default control templates](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Misc.xml)for details.
|
||||
|
||||
## \<DatePicker\> Properties
|
||||
|
||||
@@ -14,35 +18,41 @@ The default value is the today provided by the OS.
|
||||
|
||||
### DateFormat (DateFormatChanged)
|
||||
|
||||
The default value is first value in ** Locale::UserDefault() `missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html`. GetLongDateFormats() `missing document: /vlppos/ref/VL__LOCALE__GETLONGDATEFORMATS@VOID(__VL__COLLECTIONS__LIST___VL.html`**.
|
||||
The default value is first value in**Locale::UserDefault()`missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html`.GetLongDateFormats()`missing document: /vlppos/ref/VL__LOCALE__GETLONGDATEFORMATS@VOID(__VL__COLLECTIONS__LIST___VL.html`**.
|
||||
|
||||
A valid value for this property must satisfy FormatDate`missing document: /vlppos/ref/VL__LOCALE__FORMATDATE@__VL__WSTRING(__VL__WSTRING_CONST_&,___VL.html` of the current **DateLocale** value.
|
||||
A valid value for this property must satisfyFormatDate`missing document: /vlppos/ref/VL__LOCALE__FORMATDATE@__VL__WSTRING(__VL__WSTRING_CONST_&,___VL.html`of the current**DateLocale**value.
|
||||
|
||||
### DateLocale (DateLocaleChanged)
|
||||
|
||||
The default value is first value in Locale::UserDefault()`missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html`.
|
||||
The default value is first value inLocale::UserDefault()`missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html`.
|
||||
|
||||
A valid value for this property must be either: - Locale::Locale()`missing document: /vlppos/ref/VL__LOCALE__$__CTOR@(__VL__WSTRING_CONST_&).html` - Locale::UserDefault()`missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html` - Locale::SystemDefault()`missing document: /vlppos/ref/VL__LOCALE__SYSTEMDEFAULT@__VL__LOCALE().html` - Any values in Locale::Enumerate()`missing document: /vlppos/ref/VL__LOCALE__ENUMERATE@VOID(__VL__COLLECTIONS__LIST___VL__LOCALE_.html`
|
||||
A valid value for this property must be either:
|
||||
- Locale::Locale()`missing document: /vlppos/ref/VL__LOCALE__$__CTOR@(__VL__WSTRING_CONST_&).html`
|
||||
- Locale::UserDefault()`missing document: /vlppos/ref/VL__LOCALE__USERDEFAULT@__VL__LOCALE().html`
|
||||
- Locale::SystemDefault()`missing document: /vlppos/ref/VL__LOCALE__SYSTEMDEFAULT@__VL__LOCALE().html`
|
||||
- Any values inLocale::Enumerate()`missing document: /vlppos/ref/VL__LOCALE__ENUMERATE@VOID(__VL__COLLECTIONS__LIST___VL__LOCALE_.html`
|
||||
|
||||
When **DateLocale** is changed, **DateFormat** will also be changed.
|
||||
When**DateLocale**is changed,**DateFormat**will also be changed.
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_datepicker](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_datepicker/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_datepicker](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_datepicker/Resource.xml)
|
||||
- 
|
||||
|
||||
### Text
|
||||
|
||||
This is a read-only property, calling **SetText** does nothing.
|
||||
This is a read-only property, calling**SetText**does nothing.
|
||||
|
||||
The value is **DateLocale.FormatDate(Date, DateFormat)**.
|
||||
The value is**DateLocale.FormatDate(Date, DateFormat)**.
|
||||
|
||||
## \<DatePicker\> Events
|
||||
|
||||
### DateChanged
|
||||
|
||||
This event raises when **Date** is changed.
|
||||
This event raises when**Date**is changed.
|
||||
|
||||
In the default control templates, **Date** will also be changed when **DateNavigated** or **DateSelected** raises.
|
||||
In the default control templates,**Date**will also be changed when**DateNavigated**or**DateSelected**raises.
|
||||
|
||||
### DateNavigated
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
# Basic Controls
|
||||
|
||||
Controls visualize data and react to user input. **\<Window/\>** is also a control.
|
||||
Controls visualize data and react to user input.**\<Window/\>**is also a control.
|
||||
|
||||
Use **SafeDeleteControl** and **SafeDeleteComposition** to delete a control or a composition containing controls. Otherwise memory leaks may happen.
|
||||
Use**SafeDeleteControl**and**SafeDeleteComposition**to delete a control or a composition containing controls. Otherwise memory leaks may happen.
|
||||
|
||||
A control has three main composition properties: - **BoundsComposition**: This is a composition of the control's border. To make a control appear inside another composition, just simply adds **BoundsComposition** as a child composition to that composition. - **ContainerComposition**: This is a composition of the control's inner border. To make another composition inside a control, just simply adds that composition as a child composition to **ContainerComposition**. - **FocusComposition**: If a control is focusable, this property returns a non-null value. **FocusComposition** receives [most of composition events](../../../.././gacui/components/compositions/events.md). Ideally, events provided by the control itself is sufficient enough, **FocusComposition** is designed for the implementation of the control and the control template. **BoundsComposition** and **ContainerComposition** will not change during a control's life time. **FocusComposition** changes when the control template changes.
|
||||
A control has three main composition properties:
|
||||
- **BoundsComposition**: This is a composition of the control's border. To make a control appear inside another composition, just simply adds**BoundsComposition**as a child composition to that composition.
|
||||
- **ContainerComposition**: This is a composition of the control's inner border. To make another composition inside a control, just simply adds that composition as a child composition to**ContainerComposition**.
|
||||
- **FocusComposition**: If a control is focusable, this property returns a non-null value.**FocusComposition**receives[most of composition events](../../../.././gacui/components/compositions/events.md). Ideally, events provided by the control itself is sufficient enough,**FocusComposition**is designed for the implementation of the control and the control template.**BoundsComposition**and**ContainerComposition**will not change during a control's life time.**FocusComposition**changes when the control template changes.
|
||||
|
||||
Many properties are shared across control classes.
|
||||
|
||||
@@ -14,73 +17,77 @@ The following properties and events control states for a control.
|
||||
|
||||
### VisuallyEnabled (VisuallyEnabledChanged)
|
||||
|
||||
When a control's **Enabled** is set to **false**, **VisuallyEnalbed** of the control itself and all direct or indirect child controls is also set to **false**.
|
||||
When a control's**Enabled**is set to**false**,**VisuallyEnalbed**of the control itself and all direct or indirect child controls is also set to**false**.
|
||||
|
||||
A visually disabled control doesn't react to user input.
|
||||
|
||||
**VisuallyEnabled** of the control template automatically updates when this property is changed.
|
||||
**VisuallyEnabled**of the control template automatically updates when this property is changed.
|
||||
|
||||
### Enabled (EnabledChanged)
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When a control's **Enabled** is set to **false**, **VisuallyEnalbed** of the control itself and all direct or indirect child controls is also set to **false**.
|
||||
When a control's**Enabled**is set to**false**,**VisuallyEnalbed**of the control itself and all direct or indirect child controls is also set to**false**.
|
||||
|
||||
A visually disabled control doesn't react to user input.
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_enabled](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_enabled/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_enabled](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_enabled/Resource.xml)
|
||||
- 
|
||||
|
||||
### Visible (VisibleChanged)
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When a control's **Visible** is set to **false**, the control disappears, but it still affect the minimum size of all parent compositions.
|
||||
When a control's**Visible**is set to**false**, the control disappears, but it still affect the minimum size of all parent compositions.
|
||||
|
||||
### Text (TextChanged)
|
||||
|
||||
The default value for this property is **""**.
|
||||
The default value for this property is**""**.
|
||||
|
||||
This property controls the text displayed on the control.
|
||||
|
||||
**Text** of the control template automatically updates when this property is changed.
|
||||
**Text**of the control template automatically updates when this property is changed.
|
||||
|
||||
### DisplayFont (DisplayFontChanged)
|
||||
|
||||
**DisplayFont** reflects the expected font for this control.
|
||||
**DisplayFont**reflects the expected font for this control.
|
||||
|
||||
The expected font for this control is, either the **Font** of this control if it is not empty, or the nearest parent control's non-empty **Font**. If no font is found all the way to the top level control, it becomes **GetCurrentController()-\>ResourceService()-\>GetDefaultFont()**
|
||||
The expected font for this control is, either the**Font**of this control if it is not empty, or the nearest parent control's non-empty**Font**. If no font is found all the way to the top level control, it becomes**GetCurrentController()-\>ResourceService()-\>GetDefaultFont()**
|
||||
|
||||
**DisplayFont** of the control template automatically updates when this property is changed.
|
||||
**DisplayFont**of the control template automatically updates when this property is changed.
|
||||
|
||||
### Font (FontChanged)
|
||||
|
||||
The default value for this property is **null**.
|
||||
The default value for this property is**null**.
|
||||
|
||||
When a control's **Font** is changed, **DisplayFont** of the control itself and all direct or indirect child controls with an empty **Font** is also changed,
|
||||
When a control's**Font**is changed,**DisplayFont**of the control itself and all direct or indirect child controls with an empty**Font**is also changed,
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_font](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_font/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_font](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_font/Resource.xml)
|
||||
- 
|
||||
|
||||
### Context (ContextChanged)
|
||||
|
||||
The default value for this property is **null**.
|
||||
The default value for this property is**null**.
|
||||
|
||||
This property offers a way to communicate between a control and its control template or item templates. When the value is changed, the **Context** property of its control template or item templates will be changed to that value.
|
||||
This property offers a way to communicate between a control and its control template or item templates. When the value is changed, the**Context**property of its control template or item templates will be changed to that value.
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/TriplePhaseImageButton) as an example. In this project, it creates a new control **TriplePhaseButton** which has different images for different states. This new control passes itself to the **Context** of a button inside this control, and than the control template of this button communicates directly to this new control, to make the button behaves like a triple-phases button (unlike double-phases buttons like check boxes).
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/TriplePhaseImageButton)as an example. In this project, it creates a new control**TriplePhaseButton**which has different images for different states. This new control passes itself to the**Context**of a button inside this control, and than the control template of this button communicates directly to this new control, to make the button behaves like a triple-phases button (unlike double-phases buttons like check boxes).
|
||||
|
||||
### Focused (FocusedChanged)
|
||||
|
||||
The default value for this property is **false**.
|
||||
The default value for this property is**false**.
|
||||
|
||||
Calling **SetFocus** to try to move focus to this control. A focused control accepts keyboard and character input to the window.
|
||||
Calling**SetFocus**to try to move focus to this control. A focused control accepts keyboard and character input to the window.
|
||||
|
||||
### Tag
|
||||
|
||||
The default value for this property is **null**.
|
||||
The default value for this property is**null**.
|
||||
|
||||
This property accepts any value. It does nothing but associates a value to a control.
|
||||
|
||||
@@ -90,33 +97,33 @@ The following properties and events control the control template for a control.
|
||||
|
||||
### ControlThemeName (ControlThemeNameChanged)
|
||||
|
||||
A **ThemeTemplates** contains control template implementations for controls. Each control template factory fields are optional. Multiple **ThemeTemplates** could be registered and unregistered using **RegisterTheme** and **UnregisteredTheme**. The later registered **ThemeTemplates** has a higher pririty.
|
||||
A**ThemeTemplates**contains control template implementations for controls. Each control template factory fields are optional. Multiple**ThemeTemplates**could be registered and unregistered using**RegisterTheme**and**UnregisteredTheme**. The later registered**ThemeTemplates**has a higher pririty.
|
||||
|
||||
When calling **GetCurrentTheme-\>CreateStyle(themeName)**, it goes through all registered theme and find if any **ThemeTemplates** has an implementation for the specified **themeName**.
|
||||
When calling**GetCurrentTheme-\>CreateStyle(themeName)**, it goes through all registered theme and find if any**ThemeTemplates**has an implementation for the specified**themeName**.
|
||||
|
||||
**ControlThemeName** property specifies which control template should be used for this template.
|
||||
**ControlThemeName**property specifies which control template should be used for this template.
|
||||
|
||||
Different control classes have different default values for this property. In most of the cases this property is not expected to be changed during the runtime.
|
||||
|
||||
When **ControlThemeName** is changed and **ControlTemplate** is empty, the control template for this control will be changed immediately. **SetControlThemeNameAndTemplate** is for changing both **ControlThemeName** and **ControlTemplate** at the same time to improve the performance.
|
||||
When**ControlThemeName**is changed and**ControlTemplate**is empty, the control template for this control will be changed immediately.**SetControlThemeNameAndTemplate**is for changing both**ControlThemeName**and**ControlTemplate**at the same time to improve the performance.
|
||||
|
||||
### ControlTemplate (ControlTemplateChanged)
|
||||
|
||||
This property is used when you doesn't want the registered control template for this control.
|
||||
|
||||
The default value for this property is empty. The value for this property must be a **vl::Func** for the function type **templates::GuiControlTemplate*(const reflection::description::Value&)**.
|
||||
The default value for this property is empty. The value for this property must be a**vl::Func**for the function type**templates::GuiControlTemplate*(const reflection::description::Value&)**.
|
||||
|
||||
Please check out [ this page ](../../../.././gacui/xmlres/instance/properties.md) for details about using this property in GacUI XML Resource.
|
||||
Please check out[this page](../../../.././gacui/xmlres/instance/properties.md)for details about using this property in GacUI XML Resource.
|
||||
|
||||
When **ControlTemplate** is assigned with an empty value, **ControlThemeName** kicks in and update the control template for this control. When **ControlTemplate** is assigned with a non-empty value, this property is evaluated to create a control template for this control. **SetControlThemeNameAndTemplate** is for changing both **ControlThemeName** and **ControlTemplate** at the same time to improve the performance.
|
||||
When**ControlTemplate**is assigned with an empty value,**ControlThemeName**kicks in and update the control template for this control. When**ControlTemplate**is assigned with a non-empty value, this property is evaluated to create a control template for this control.**SetControlThemeNameAndTemplate**is for changing both**ControlThemeName**and**ControlTemplate**at the same time to improve the performance.
|
||||
|
||||
### ControlTemplateObject
|
||||
|
||||
This property returns the currently used control template instance.
|
||||
|
||||
A control template is also a composition, and it has **BoundsComposition** and **ContainerComposition** too. But they are not same values as the same property of the control.
|
||||
A control template is also a composition, and it has**BoundsComposition**and**ContainerComposition**too. But they are not same values as the same property of the control.
|
||||
|
||||
**FocusComposition** is the same to control and control templates.
|
||||
**FocusComposition**is the same to control and control templates.
|
||||
|
||||
## Context
|
||||
|
||||
@@ -124,15 +131,15 @@ The following properties and events provide access of the control's context.
|
||||
|
||||
### Parent (ControlSignalTrigerred with ParentLineChanged)
|
||||
|
||||
A control appears inside its **Parent**, otherwise this property returns **null** (usually for windows and menus).
|
||||
A control appears inside its**Parent**, otherwise this property returns**null**(usually for windows and menus).
|
||||
|
||||
To add a control directly inside another control, just simply call **AddChild**, which adds the child control's **BoundsComposition** to the parent control's **ContainerComposition**. It is also OK when the child control's **BoundsComposition** is not the direct child composition of the parent control's **ContainerComposition**.
|
||||
To add a control directly inside another control, just simply call**AddChild**, which adds the child control's**BoundsComposition**to the parent control's**ContainerComposition**. It is also OK when the child control's**BoundsComposition**is not the direct child composition of the parent control's**ContainerComposition**.
|
||||
|
||||
**GetChildrenCount**, **GetChild** and **HasChild** provide access for child controls.
|
||||
**GetChildrenCount**,**GetChild**and**HasChild**provide access for child controls.
|
||||
|
||||
### RelatedControlHost (ControlSignalTrigerred with ParentLineChanged)
|
||||
|
||||
**RelatedControlHost** is the root parent control for a control, which is usually a window or a menu. otherwise this property returns **null** (usually for windows and menus).
|
||||
**RelatedControlHost**is the root parent control for a control, which is usually a window or a menu. otherwise this property returns**null**(usually for windows and menus).
|
||||
|
||||
## Behaviors
|
||||
|
||||
@@ -140,51 +147,60 @@ The following properties and events control the behavior of a control.
|
||||
|
||||
### AcceptTabInput
|
||||
|
||||
The default value for this property **true**.
|
||||
The default value for this property**true**.
|
||||
|
||||
When this property is set to **true**, pressing **TAB** key when this control is focused type a **TAB** character into this control.
|
||||
When this property is set to**true**, pressing**TAB**key when this control is focused type a**TAB**character into this control.
|
||||
|
||||
### TabPriority
|
||||
|
||||
The default value for this property is **-1**.
|
||||
The default value for this property is**-1**.
|
||||
|
||||
Pressing **TAB** in a window cause the focus to move between all controls that have a non-negative value **TabProperty** from low to high.
|
||||
Pressing**TAB**in a window cause the focus to move between all controls that have a non-negative value**TabProperty**from low to high.
|
||||
|
||||
### Alt (AltChanged)
|
||||
|
||||
The default value for this property is **""**.
|
||||
The default value for this property is**""**.
|
||||
|
||||
Pressing **ALT** causes a window prints all acceptable keys to move focus to all controls that have a non-empty **Alt**.
|
||||
Pressing**ALT**causes a window prints all acceptable keys to move focus to all controls that have a non-empty**Alt**.
|
||||
|
||||
**Alt** could contain multiple upper-cased letters and digits, which is a sequence that moves the focus to this control after pressing **ALT**.
|
||||
**Alt**could contain multiple upper-cased letters and digits, which is a sequence that moves the focus to this control after pressing**ALT**.
|
||||
|
||||
For controls that are not focusable but manage focus of direct child controls (like Tab control), or for controls that manage focus of child controls in another window (like menus), **SetActivatingAltHost** is an important function to activate this feature for this control. This function is only for control authors to use. Pressing **ESC** or **BACKSPACE** goes back to the upper level window or control during a **ALT** sequence.
|
||||
For controls that are not focusable but manage focus of direct child controls (like Tab control), or for controls that manage focus of child controls in another window (like menus),**SetActivatingAltHost**is an important function to activate this feature for this control. This function is only for control authors to use. Pressing**ESC**or**BACKSPACE**goes back to the upper level window or control during a**ALT**sequence.
|
||||
|
||||
### TooltipControl
|
||||
|
||||
The default value for this property is **null**.
|
||||
The default value for this property is**null**.
|
||||
|
||||
A legal value for this property must be a control that is not contained in any composition. When the mouse stops on a control for a while, its **TooltipControl** will appear at the mouse cursor.
|
||||
A legal value for this property must be a control that is not contained in any composition. When the mouse stops on a control for a while, its**TooltipControl**will appear at the mouse cursor.
|
||||
|
||||
When a control is deleted, it also deletes its **TooltipControl**.
|
||||
When a control is deleted, it also deletes its**TooltipControl**.
|
||||
|
||||
**DisplayTooltip** and **CloseTooltip** could be call to manually control a tooltip proactively.
|
||||
**DisplayTooltip**and**CloseTooltip**could be call to manually control a tooltip proactively.
|
||||
|
||||
### TooltipWidth
|
||||
|
||||
The default value for this property is **0**.
|
||||
The default value for this property is**0**.
|
||||
|
||||
This property controls the width of **TooltipControl**.
|
||||
This property controls the width of**TooltipControl**.
|
||||
|
||||
#### Sample
|
||||
|
||||
- Source code: [control_basic_tooltip](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_tooltip/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_tooltip](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_tooltip/Resource.xml)
|
||||
- 
|
||||
|
||||
## Service Objects
|
||||
|
||||
**AddService** (ControlSignalTrigerred with ServiceAdded) associates a nullable service object to this control with an identifier that could be any string.
|
||||
**AddService**(ControlSignalTrigerred with ServiceAdded) associates a nullable service object to this control with an identifier that could be any string.
|
||||
|
||||
**QueryService** or **QueryTypedService\<T\>** searches for a service object using an identifier all the way up to the top-level control. If multiple service objects are found, the one in the nearest parent control wins.
|
||||
**QueryService**or**QueryTypedService\<T\>**searches for a service object using an identifier all the way up to the top-level control. If multiple service objects are found, the one in the nearest parent control wins.
|
||||
|
||||
Some service identifiers are hard-coded in controls, even if you try to associate a service objects using thses identifiers, it takes no effect on some controls: - vl::presentation::compositions::IGuiAltAction - vl::presentation::compositions::IGuiAltActionContainer - vl::presentation::compositions::IGuiAltActionHost - vl::presentation::controls::IGuiMenuService - vl::presentation::controls::IGuiMenuDropdownProvider - vl::presentation::controls::IToolstripUpdateLayoutInvoker - vl::presentation::compositions::IGuiTabAction Predefined services are full name of GacUI classes, it is easy to avoid conflict with your own service objects.
|
||||
Some service identifiers are hard-coded in controls, even if you try to associate a service objects using thses identifiers, it takes no effect on some controls:
|
||||
- vl::presentation::compositions::IGuiAltAction
|
||||
- vl::presentation::compositions::IGuiAltActionContainer
|
||||
- vl::presentation::compositions::IGuiAltActionHost
|
||||
- vl::presentation::controls::IGuiMenuService
|
||||
- vl::presentation::controls::IGuiMenuDropdownProvider
|
||||
- vl::presentation::controls::IToolstripUpdateLayoutInvoker
|
||||
- vl::presentation::compositions::IGuiTabActionPredefined services are full name of GacUI classes, it is easy to avoid conflict with your own service objects.
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# \<Label\>
|
||||
|
||||
- **\<Label/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiLabel* - **Template Tag**: \<LabelTemplate/\> - **Template Name**: Label
|
||||
|
||||
**\<Label/\>** displays text in a specified font and color.
|
||||
- **\<Label/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiLabel*
|
||||
- **Template Tag**: \<LabelTemplate/\>
|
||||
- **Template Name**: Label
|
||||
|
||||
**\<Label/\>** uses **Text** and **Font** properties to display text. If no minimum size is specified for **\<Label/\>**, the control always resize itself just enough to display all characters. Multiple lines of text are allowed, but one line doesn't wrap to multiple lines if the width of the control is not long enough.
|
||||
**\<Label/\>**displays text in a specified font and color.
|
||||
|
||||
**TextColor** defines the color of the text, the default value is the **DefaultTextColor** from its control template. You can change **\<Label/\>::TextColor** to override **\<LabelTemplate/\>::DefaultTextColor**, but if **TextColor** have the same value of **DefaultTextColor**, it is marked as "not overriding", and it changes if the control switch to another control template with a different **DefaultTextColor**.
|
||||
**\<Label/\>**uses**Text**and**Font**properties to display text. If no minimum size is specified for**\<Label/\>**, the control always resize itself just enough to display all characters. Multiple lines of text are allowed, but one line doesn't wrap to multiple lines if the width of the control is not long enough.
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Xml/Instance_Window/UI/Resource.xml) for details.
|
||||
**TextColor**defines the color of the text, the default value is the**DefaultTextColor**from its control template. You can change**\<Label/\>::TextColor**to override**\<LabelTemplate/\>::DefaultTextColor**, but if**TextColor**have the same value of**DefaultTextColor**, it is marked as "not overriding", and it changes if the control switch to another control template with a different**DefaultTextColor**.
|
||||
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Xml/Instance_Window/UI/Resource.xml)for details.
|
||||
|
||||
|
||||
@@ -1,64 +1,78 @@
|
||||
# GuiScroll
|
||||
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiScroll* - **Template Tag**: \<ScrollTemplate/\> - **\<HScroll/\>** - **Template Name**: HScroll - **\<VScroll/\>** - **Template Name**: VScroll - **\<HTracker/\>** - **Template Name**: HTracker - **\<VTracker/\>** - **Template Name**: VTracker - **\<ProgressBar/\>** - **Template Name**: ProgressBar Dragging the handler is not easy to implement and it is very commonly required for **GuiScroll**, so **\<CommonScrollBehavior/\>** is provided for writing such control templates. Please check out [ the default control templates ](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml) for details.
|
||||
|
||||
**HScroll** or **VScroll** have a slider with two buttons for controlling a position.
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiScroll*
|
||||
- **Template Tag**: \<ScrollTemplate/\>
|
||||
- **\<HScroll/\>**
|
||||
- **Template Name**: HScroll
|
||||
- **\<VScroll/\>**
|
||||
- **Template Name**: VScroll
|
||||
- **\<HTracker/\>**
|
||||
- **Template Name**: HTracker
|
||||
- **\<VTracker/\>**
|
||||
- **Template Name**: VTracker
|
||||
- **\<ProgressBar/\>**
|
||||
- **Template Name**: ProgressBarDragging the handler is not easy to implement and it is very commonly required for**GuiScroll**, so**\<CommonScrollBehavior/\>**is provided for writing such control templates. Please check out[the default control templates](https://github.com/vczh-libraries/GacUI/blob/master/Source/Skins/DarkSkin/Template_Scroll.xml)for details.
|
||||
|
||||
**HTracker** or **VTracker** have only a slider for controlling a position.
|
||||
**HScroll**or**VScroll**have a slider with two buttons for controlling a position.
|
||||
|
||||
**ProgressBar** only displays a position.
|
||||
**HTracker**or**VTracker**have only a slider for controlling a position.
|
||||
|
||||
**ProgressBar**only displays a position.
|
||||
|
||||
## GuiScroll Properties
|
||||
|
||||
### TotalSize (TotalSizeChanged)
|
||||
|
||||
The default value for this property is **100**.
|
||||
The default value for this property is**100**.
|
||||
|
||||
This property represents the total size of a logical concept.
|
||||
|
||||
### PageSize (PageSizeChanged)
|
||||
|
||||
The default value for this property is **10**. For **\<HTracker/\>**, **\<VTracker/\>** and **\<ProgressBar/\>**, this property is set to **0** right after constructors are called.
|
||||
The default value for this property is**10**. For**\<HTracker/\>**,**\<VTracker/\>**and**\<ProgressBar/\>**, this property is set to**0**right after constructors are called.
|
||||
|
||||
This property represents the view port size of a logical concept.
|
||||
|
||||
In default control templates for **HScroll** and **VScroll**, this property affect the size of the slider, it takes **PageSize/TotalSize** of the space that is not covered by the two buttons.
|
||||
In default control templates for**HScroll**and**VScroll**, this property affect the size of the slider, it takes**PageSize/TotalSize**of the space that is not covered by the two buttons.
|
||||
|
||||
### Position (PositionChanged)
|
||||
|
||||
The default value for this property is **0**.
|
||||
The default value for this property is**0**.
|
||||
|
||||
The property represents the position of the view port of a logical concept.
|
||||
|
||||
A legal value must be in **[MinPosition, MaxPosition]**.
|
||||
A legal value must be in**[MinPosition, MaxPosition]**.
|
||||
|
||||
### SmallMove (SmallMoveChanged)
|
||||
|
||||
The default value for this property is **1**.
|
||||
The default value for this property is**1**.
|
||||
|
||||
This property describes how much the position will be increased or decreased by clicking the two buttons (if exist).
|
||||
|
||||
### BigMove (BigMoveChanged)
|
||||
|
||||
The default value for this property is **10**.
|
||||
The default value for this property is**10**.
|
||||
|
||||
This property describes how much the position will be increased or decreased by clicking the remaining space of a scroll that is not covered by the two buttons and the slider.
|
||||
|
||||
Usually it is recommended to keep **PageSize** and **BigMove** being the same for **\<HScroll/\>** and **\<VScroll/\>**, but it is up to you.
|
||||
Usually it is recommended to keep**PageSize**and**BigMove**being the same for**\<HScroll/\>**and**\<VScroll/\>**, but it is up to you.
|
||||
|
||||
### MinPosition
|
||||
|
||||
This property is always **0**.
|
||||
This property is always**0**.
|
||||
|
||||
### MaxPosition
|
||||
|
||||
This property is always **TotalSize - PageSize**.
|
||||
This property is always**TotalSize - PageSize**.
|
||||
|
||||
### AutoFocus
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When this property is **true**: - The scroll is focused when the mouse button is pressed. - The scroll is focused when it is executed by **TAB** or a **ALT** sequence.
|
||||
When this property is**true**:
|
||||
- The scroll is focused when the mouse button is pressed.
|
||||
- The scroll is focused when it is executed by**TAB**or a**ALT**sequence.
|
||||
|
||||
When a scroll is focused, pressing **HOME**, **END**, **PAGE UP**, **PAGE DOWN**, **Left**, **Up**, **Right**, **Down** could change **Position**. In order to correctly transfer the focus to **GuiScroll**, buttons in this control should have **AutoFocus** set to **false**.
|
||||
When a scroll is focused, pressing**HOME**,**END**,**PAGE UP**,**PAGE DOWN**,**Left**,**Up**,**Right**,**Down**could change**Position**. In order to correctly transfer the focus to**GuiScroll**, buttons in this control should have**AutoFocus**set to**false**.
|
||||
|
||||
|
||||
@@ -1,38 +1,49 @@
|
||||
# GuiSelectableButton
|
||||
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiSelectableButton* - **Template Tag**: \<SelectableButtonTemplate/\> - **\<CheckBox/\>** - **Template Name**: CheckBox - **\<RadioButton/\>** - **Template Name**: RadioButton
|
||||
|
||||
**GuiSelectableButton** is a **\<Button/\>** with the ability to be selected.
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiSelectableButton*
|
||||
- **Template Tag**: \<SelectableButtonTemplate/\>
|
||||
- **\<CheckBox/\>**
|
||||
- **Template Name**: CheckBox
|
||||
- **\<RadioButton/\>**
|
||||
- **Template Name**: RadioButton
|
||||
|
||||
Usually, **\<CheckBox/\>** represents an independent option, and multiple **\<RadioButton/\>** represent a group of exclusive choices.
|
||||
**GuiSelectableButton**is a**\<Button/\>**with the ability to be selected.
|
||||
|
||||
Usually,**\<CheckBox/\>**represents an independent option, and multiple**\<RadioButton/\>**represent a group of exclusive choices.
|
||||
|
||||
## GuiSelectableButton Properties
|
||||
|
||||
### AutoSelection (AutoSelectionChanged)
|
||||
|
||||
The default value for this property is **true**, but it could be different in sub classes.
|
||||
The default value for this property is**true**, but it could be different in sub classes.
|
||||
|
||||
When this property is **true**, the **Selected** property reverses when **Clicked** raises, otherwise, the **Selected** property is not changed automatically, but it could be changed by code.
|
||||
When this property is**true**, the**Selected**property reverses when**Clicked**raises, otherwise, the**Selected**property is not changed automatically, but it could be changed by code.
|
||||
|
||||
### Selected (SelectedChanged)
|
||||
|
||||
The default value for this property is **false**.
|
||||
The default value for this property is**false**.
|
||||
|
||||
This property doesn't change behaviors, it is used to record a selection and tell the control template to render differently.
|
||||
|
||||
### GroupController (GroupControllerChanged)
|
||||
|
||||
The default value for this property is **null**.
|
||||
The default value for this property is**null**.
|
||||
|
||||
A **GuiSelectableButton::GroupController** instance is required for this property. **GuiSelectableButton::MutexGroupController** is a predefined group controller to make **\<RadioButton/\>** exclusive to each other.
|
||||
A**GuiSelectableButton::GroupController**instance is required for this property.**GuiSelectableButton::MutexGroupController**is a predefined group controller to make**\<RadioButton/\>**exclusive to each other.
|
||||
|
||||
typical steps to create a group of **\<RadioButton/\>**: - Create a namespace mapping if necessary, like **xmlns:x="presentation::controls::GuiSelectableButton::*"** - Create one **\<x:MutexGroupController/\>** for each group of radio buttons, as a component for the current **\<Instance/\>**. - Assign **GroupController** of radio buttons in the same group to the same **\<x:MutexGroupController/\>****NOTE:****"xmlns:x"** is just a name, you can map the namespace to any name you like. If you call it **"xmlns:abc"**, then the controller becomes **\<abc:MutexGroupController/\>**.
|
||||
typical steps to create a group of**\<RadioButton/\>**:
|
||||
- Create a namespace mapping if necessary, like**xmlns:x="presentation::controls::GuiSelectableButton::*"**
|
||||
- Create one**\<x:MutexGroupController/\>**for each group of radio buttons, as a component for the current**\<Instance/\>**.
|
||||
- Assign**GroupController**of radio buttons in the same group to the same**\<x:MutexGroupController/\>****NOTE:****"xmlns:x"**is just a name, you can map the namespace to any name you like. If you call it**"xmlns:abc"**, then the controller becomes**\<abc:MutexGroupController/\>**.
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/TextListTabPage.xml) for **\<CheckBox/\>**, **\<RadioButton/\>** and **\<x:MutexGroupController/\>**
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/TextListTabPage.xml)for**\<CheckBox/\>**,**\<RadioButton/\>**and**\<x:MutexGroupController/\>**
|
||||
|
||||
You could create a new class and inherit from **GuiSelectableButton::GroupController** and use it in the **GroupController** property, for a scenario like "only 3 options could be selected", and automatically canceled the oldest option when 4 options are selected. But in order to prevent users from being confused, error messages are recommended instead of changing users' input.
|
||||
You could create a new class and inherit from**GuiSelectableButton::GroupController**and use it in the**GroupController**property, for a scenario like "only 3 options could be selected", and automatically canceled the oldest option when 4 options are selected. But in order to prevent users from being confused, error messages are recommended instead of changing users' input.
|
||||
|
||||
## Sample
|
||||
|
||||
- Source code: [control_basic_checkbox](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_checkbox/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_checkbox](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_checkbox/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,46 +1,64 @@
|
||||
# ControlHost and \<Window\>
|
||||
|
||||
- **\<Window/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiWindow* - **Template Tag**: \<WindowTemplate/\> - **Template Name**: Window
|
||||
|
||||
**\<Window/\>** is where we start our journey. ``` <Instance ref.CodeBehind="false" ref.Class="demo::MainWindow> <Window ref.Name="self" Text="This is the main window" ClientSize="x:640 y:480"> <att.BoundsComposition-set PreferredMinSize="x:480 y:320"> <!-- Here to put contents inside a window --> </Window> </Instance> ``` - **\<Window/\>** is a **ControlHost**, which has to be a top-level window, is usually a base class of an [ <Instance> ](../../../.././gacui/xmlres/tag_instance.md). Here we create a class **demo::MainWindow** inheriting from **\<Window/\>**. - **ref.CodeBehind** set to **false** so that GacUI doesn't generate a separated pair of C++ source files for this class. - **Text** is the title of this window. - **ClientSize** is the initial size when the window is loaded. This size doesn't include the border and the title. - **BoundsComposition.PreferredMinSize** is the minimum client size of this window. When the window size is being changed by dragging the border, it cannot go smaller than this size.
|
||||
- **\<Window/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiWindow*
|
||||
- **Template Tag**: \<WindowTemplate/\>
|
||||
- **Template Name**: Window
|
||||
|
||||
**\<Window/\>**is where we start our journey.
|
||||
```
|
||||
<Instance ref.CodeBehind="false" ref.Class="demo::MainWindow>
|
||||
<Window ref.Name="self" Text="This is the main window" ClientSize="x:640 y:480">
|
||||
<att.BoundsComposition-set PreferredMinSize="x:480 y:320">
|
||||
<!-- Here to put contents inside a window -->
|
||||
</Window>
|
||||
</Instance>
|
||||
```
|
||||
|
||||
- **\<Window/\>**is a**ControlHost**, which has to be a top-level window, is usually a base class of an[<Instance>](../../../.././gacui/xmlres/tag_instance.md). Here we create a class**demo::MainWindow**inheriting from**\<Window/\>**.
|
||||
- **ref.CodeBehind**set to**false**so that GacUI doesn't generate a separated pair of C++ source files for this class.
|
||||
- **Text**is the title of this window.
|
||||
- **ClientSize**is the initial size when the window is loaded. This size doesn't include the border and the title.
|
||||
- **BoundsComposition.PreferredMinSize**is the minimum client size of this window. When the window size is being changed by dragging the border, it cannot go smaller than this size.
|
||||
|
||||
## Adding something to a window
|
||||
|
||||
**\<Window/\>** is just a control. Compositions and controls in the window will be added to its **ContainerComposition**. You don't have to explicitly use **att.ContainerComposition**.
|
||||
**\<Window/\>**is just a control. Compositions and controls in the window will be added to its**ContainerComposition**. You don't have to explicitly use**att.ContainerComposition**.
|
||||
|
||||
As a **GuiInstanceRootObject**, components can also be added to a window.
|
||||
As a**GuiInstanceRootObject**, components can also be added to a window.
|
||||
|
||||
Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Xml/Instance_Window) for details.
|
||||
Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Xml/Instance_Window)for details.
|
||||
|
||||
## GuiControlHost Properties
|
||||
|
||||
### Focused (WindowGotFocus, WindowLostFocus)
|
||||
|
||||
A focused window receives keyboard inputs. It will deliver all inputs to the focused control, except for **ALT** sequence.
|
||||
A focused window receives keyboard inputs. It will deliver all inputs to the focused control, except for**ALT**sequence.
|
||||
|
||||
### Activated (WindowActivated, WindowDeactivated)
|
||||
|
||||
A focused window must be activated.
|
||||
|
||||
Calling **SetParent** of a control host's **NativeWindow** makes a becomes another window's sub window.
|
||||
Calling**SetParent**of a control host's**NativeWindow**makes a becomes another window's sub window.
|
||||
|
||||
### ShowInTaskBar
|
||||
|
||||
The default value is different in different sub classes.
|
||||
|
||||
When this property is set to **true**, a icon (and probably with text) appears in the task bar.
|
||||
When this property is set to**true**, a icon (and probably with text) appears in the task bar.
|
||||
|
||||
### EnableActivate
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When this property is set to **false**, this window is not allowed to be activated by user interaction. But this property will be automatically set to **false** when the window is required to be activated by code. For example, calling **Show** instead of **ShowDeactivated**, or calling **SetActivated**.
|
||||
When this property is set to**false**, this window is not allowed to be activated by user interaction. But this property will be automatically set to**false**when the window is required to be activated by code. For example, calling**Show**instead of**ShowDeactivated**, or calling**SetActivated**.
|
||||
|
||||
### TopMost
|
||||
|
||||
The default value for this property is **false**.
|
||||
The default value for this property is**false**.
|
||||
|
||||
When this property is set to **true**, it stays in front of all windows whose **TopMost** is **false**.
|
||||
When this property is set to**true**, it stays in front of all windows whose**TopMost**is**false**.
|
||||
|
||||
### ClientSize
|
||||
|
||||
@@ -54,17 +72,17 @@ This property is the location of a window.
|
||||
|
||||
This value changes acfording to DPI or text scaling settings. The coordinate is in screen space. In a multiple monitors computer, a visible window could have negative numbers in its location.
|
||||
|
||||
**SetBounds** could be called to set **Location** and **ClientSize** at the same time.
|
||||
**SetBounds**could be called to set**Location**and**ClientSize**at the same time.
|
||||
|
||||
### TimerManager
|
||||
|
||||
This property returns a manager object that runs tasks repeatedly until the task itself tells the manager object to stop.
|
||||
|
||||
[ Animations ](../../../.././gacui/xmlres/tag_animation.md) are built on top of it.
|
||||
[Animations](../../../.././gacui/xmlres/tag_animation.md)are built on top of it.
|
||||
|
||||
### Opening
|
||||
|
||||
When this property is **true**, the window is visible.
|
||||
When this property is**true**, the window is visible.
|
||||
|
||||
## GuiControlHost Events
|
||||
|
||||
@@ -76,11 +94,11 @@ This event is raised right after a window is visible.
|
||||
|
||||
This event is raised before a window is closed.
|
||||
|
||||
The second argument for this event is a **GuiRequestEventArgs**. By setting the **cancel** field to **true**, it stops then window from being closed.
|
||||
The second argument for this event is a**GuiRequestEventArgs**. By setting the**cancel**field to**true**, it stops then window from being closed.
|
||||
|
||||
### WindowReadyToClose
|
||||
|
||||
This event is raised right before a window is closed when **WindowClosing** does not cancel the operation.
|
||||
This event is raised right before a window is closed when**WindowClosing**does not cancel the operation.
|
||||
|
||||
### WindowClosed
|
||||
|
||||
@@ -92,27 +110,44 @@ This event is raised before a window is being deleted. At this moment, everythin
|
||||
|
||||
## Displaying a GuiControlHost
|
||||
|
||||
You could **Show** or **ShowDeactivated** a window without changing its size.
|
||||
You could**Show**or**ShowDeactivated**a window without changing its size.
|
||||
|
||||
You could also **ShowRestored**, **ShowMaximized** or **ShowMinimized** a window.
|
||||
You could also**ShowRestored**,**ShowMaximized**or**ShowMinimized**a window.
|
||||
|
||||
To make a window invisible, you could call **Hide** or **Close**. Calling **Close** on the main window cause the application to begin an existing process. These two functions behaves the same for other windows.
|
||||
To make a window invisible, you could call**Hide**or**Close**. Calling**Close**on the main window cause the application to begin an existing process. These two functions behaves the same for other windows.
|
||||
|
||||
## Controlling \<Window\> Border
|
||||
|
||||
The following properties control what components should appear in the window's border: - MaximizedBox - MinimizedBox - Border - SizeBox - IconVisible - TitleBar A window's control template could accept or reject such changing by setting the following properties in **\<WindowTemplate/\>**: - MaximizedBoxOption - MinimizedBoxOption - BorderOption - SizeBoxOption - IconVisibleOption - TitleBarOption They could be **AlwaysTrue**, **AlwaysFalse** or **Customizable**.
|
||||
The following properties control what components should appear in the window's border:
|
||||
- MaximizedBox
|
||||
- MinimizedBox
|
||||
- Border
|
||||
- SizeBox
|
||||
- IconVisible
|
||||
- TitleBarA window's control template could accept or reject such changing by setting the following properties in**\<WindowTemplate/\>**:
|
||||
- MaximizedBoxOption
|
||||
- MinimizedBoxOption
|
||||
- BorderOption
|
||||
- SizeBoxOption
|
||||
- IconVisibleOption
|
||||
- TitleBarOptionThey could be**AlwaysTrue**,**AlwaysFalse**or**Customizable**.
|
||||
|
||||
### Sample
|
||||
|
||||
- Source code: [control_basic_window](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_window/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_window](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_window/Resource.xml)
|
||||
- 
|
||||
|
||||
## Displaying a \<Window\>
|
||||
|
||||
The following functions displays a **\<Window/\<** as a sub window: - **ShowModal**: This function makes a window visible as a model window. A model window will disable its owner when it is visible. The second argument will be called as a callback after this window is closed, and then its owner window becomes enabled. - **ShowModalAndDelete**: Just like **ShowModal**, but after it is closed, the window will be deleted. Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Xml/Instance_MultipleWindows) for details. It calls this function in C++ by specifying a function name in the button's **Clicked** event. With **ref.CodeBehind="true"**, a place holder is generated in [ this separated file ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Xml/Instance_MultipleWindows/UI/Source/MainWindow.cpp). - **ShowModalAsync**: Just like **ShowModal**, but it returns a **system::Async^** (or **Ptr\<reflection::description::IAsync\>** in C++). This function can be used in [$Await](../../../.././workflow/lang/coroutine_async.md), it simplies **Workflow** scripts in GacUI XML Resource a lot. Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml) and [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/DocumentEditorBase.xml) for details. They use **$Await window.ShowModalAsync(mainWindow);** followed by **delete window;** as an alternative way to **ShowModalAndDelete** without involving lambda expressions as callbacks.
|
||||
The following functions displays a**\<Window/\<**as a sub window:
|
||||
- **ShowModal**: This function makes a window visible as a model window. A model window will disable its owner when it is visible. The second argument will be called as a callback after this window is closed, and then its owner window becomes enabled.
|
||||
- **ShowModalAndDelete**: Just like**ShowModal**, but after it is closed, the window will be deleted. Please check out[this tutorial project](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Xml/Instance_MultipleWindows)for details. It calls this function in C++ by specifying a function name in the button's**Clicked**event. With**ref.CodeBehind="true"**, a place holder is generated in[this separated file](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Xml/Instance_MultipleWindows/UI/Source/MainWindow.cpp).
|
||||
- **ShowModalAsync**: Just like**ShowModal**, but it returns a**system::Async^**(or**Ptr\<reflection::description::IAsync\>**in C++). This function can be used in[$Await](../../../.././workflow/lang/coroutine_async.md), it simplies**Workflow**scripts in GacUI XML Resource a lot. Please check out[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml)and[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_ControlTemplate/BlackSkin/UI/FullControlTest/DocumentEditorBase.xml)for details. They use**$Await window.ShowModalAsync(mainWindow);**followed by**delete window;**as an alternative way to**ShowModalAndDelete**without involving lambda expressions as callbacks.
|
||||
|
||||
## \<Window\>::ClipboardUpdated Event
|
||||
|
||||
This event is raised when the content of the clipboard is changed.
|
||||
|
||||
It happens before **clipboardNotify** in any composition inside this window.
|
||||
It happens before**clipboardNotify**in any composition inside this window.
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# \<GroupBox\>
|
||||
|
||||
- **\<GroupBox/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiControl* - **Template Tag**: \<ControlTemplate/\> - **Template Name**: GroupBox
|
||||
|
||||
In the default control template, a **\<GroupBox/\>** is a container with a border and a label. Content of the label comes from the **Text** property.
|
||||
- **\<GroupBox/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiControl*
|
||||
- **Template Tag**: \<ControlTemplate/\>
|
||||
- **Template Name**: GroupBox
|
||||
|
||||
**\<GroupBox/\>** does not provide anything more than a **GuiControl**.
|
||||
In the default control template, a**\<GroupBox/\>**is a container with a border and a label. Content of the label comes from the**Text**property.
|
||||
|
||||
**\<GroupBox/\>**does not provide anything more than a**GuiControl**.
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
Unlike compositions that only layout multiple other objects in groups, container controls offer more features in user interaction.
|
||||
|
||||
**\<GroupBox/\>** is the simplest container composition which displays its **Text** with its content. Controls serving a same purpose could be grouped in a **\<GroupBox/\>**.
|
||||
**\<GroupBox/\>**is the simplest container composition which displays its**Text**with its content. Controls serving a same purpose could be grouped in a**\<GroupBox/\>**.
|
||||
|
||||
**\<ScrollContainer/\>** is a container with built-in scroll bars. When the size of the container is too small to display all its content, scroll bars will be enabled or shown.
|
||||
**\<ScrollContainer/\>**is a container with built-in scroll bars. When the size of the container is too small to display all its content, scroll bars will be enabled or shown.
|
||||
|
||||
Scroll bars are provided in **GuiScrollView**, which is the base class of **\<ScrollContainer/\>** and also all other list controls and some editor controls. **HorizontalAlwaysVisible** and **VerticalAlwaysVisible** properties also exist in list controls and some editor controls, so that their scroll bars can be optionally hidden when list items are not too many.
|
||||
Scroll bars are provided in**GuiScrollView**, which is the base class of**\<ScrollContainer/\>**and also all other list controls and some editor controls.**HorizontalAlwaysVisible**and**VerticalAlwaysVisible**properties also exist in list controls and some editor controls, so that their scroll bars can be optionally hidden when list items are not too many.
|
||||
|
||||
**\<Tab/\>** is a container of multiple **\<TabPage/\>**. Differet controls can be organized in different **\<TabPage/\>** in one **\<Tab/\>**. When a **\<TabPage/\>** is activated by the user, only contents in this page are visible, contents in other pages are hidden but still contribute to the minimum size of the **\<Tab/\>**.
|
||||
**\<Tab/\>**is a container of multiple**\<TabPage/\>**. Differet controls can be organized in different**\<TabPage/\>**in one**\<Tab/\>**. When a**\<TabPage/\>**is activated by the user, only contents in this page are visible, contents in other pages are hidden but still contribute to the minimum size of the**\<Tab/\>**.
|
||||
|
||||
|
||||
+20
-14
@@ -1,8 +1,12 @@
|
||||
# GuiScrollView and \<ScrollContainer\>
|
||||
|
||||
- **\<ScrollContainer/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiScrollContainer* - **Template Tag**: \<ScrollViewTemplate/\> - **Template Name**: ScrollView Making scroll bars dynamically visible and invisible and resizing the content area could be done using **\<Table/\>**. But such things are commonly required by container controls, list controls and editor controls. **\<CommonScrollViewLook/\>** is prepared for controlling scroll bars to help implementing control templates easier.
|
||||
|
||||
**GuiScrollView** is the base class of all controls that with a **\<HScroll/\>** and a **\<VScroll/\>**. **\<ScrollView/\>** is a ready-to-use container control that automatically shows scroll bars when content takes more spaces than the container itself.
|
||||
- **\<ScrollContainer/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiScrollContainer*
|
||||
- **Template Tag**: \<ScrollViewTemplate/\>
|
||||
- **Template Name**: ScrollViewMaking scroll bars dynamically visible and invisible and resizing the content area could be done using**\<Table/\>**. But such things are commonly required by container controls, list controls and editor controls.**\<CommonScrollViewLook/\>**is prepared for controlling scroll bars to help implementing control templates easier.
|
||||
|
||||
**GuiScrollView**is the base class of all controls that with a**\<HScroll/\>**and a**\<VScroll/\>**.**\<ScrollView/\>**is a ready-to-use container control that automatically shows scroll bars when content takes more spaces than the container itself.
|
||||
|
||||
## GuiScrollView Properties
|
||||
|
||||
@@ -12,43 +16,45 @@ This property represents the size of the visible part.
|
||||
|
||||
### ViewPosition
|
||||
|
||||
This property represents the position of the visible part. Components of **ViewPosition** are non-negative. When users scroll towards down or right, the position becomes larger.
|
||||
This property represents the position of the visible part. Components of**ViewPosition**are non-negative. When users scroll towards down or right, the position becomes larger.
|
||||
|
||||
This property could be assigned to change the position, which could cause scroll sliders move automatically.
|
||||
|
||||
### ViewBounds
|
||||
|
||||
This property is the combination of **ViewPosition** and **ViewSize**.
|
||||
This property is the combination of**ViewPosition**and**ViewSize**.
|
||||
|
||||
### HorizontalScroll and VerticalScroll
|
||||
|
||||
These properties return the **\<HScroll/\>** and the **\<VScroll/\>** of the container.
|
||||
These properties return the**\<HScroll/\>**and the**\<VScroll/\>**of the container.
|
||||
|
||||
### HorizontalAlwaysVisible
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When this property is **false**, the **\<HScroll/\>** is not visible when the width of the container is large enough to display the content.
|
||||
When this property is**false**, the**\<HScroll/\>**is not visible when the width of the container is large enough to display the content.
|
||||
|
||||
### VerticalAlwaysVisible
|
||||
|
||||
The default value for this property is **true**.
|
||||
The default value for this property is**true**.
|
||||
|
||||
When this property is **false**, the **\<VScroll/\>** is not visible when the height of the container is large enough to display the content.
|
||||
When this property is**false**, the**\<VScroll/\>**is not visible when the height of the container is large enough to display the content.
|
||||
|
||||
## \<ScrollContainer\> Properties
|
||||
|
||||
### ExtendToFullWidth or ExtendToFullHeight
|
||||
|
||||
The default value for these properties is **false**.
|
||||
The default value for these properties is**false**.
|
||||
|
||||
When **ExtendToFullWidth** is **false**, **ContainerComposition** shinks in width to contain its content. When **ExtendToFullWidth** is **true**, width of **ContainerComposition** extends to the **ViewSize** when the total width of its content doesn't exceed the width of the control.
|
||||
When**ExtendToFullWidth**is**false**,**ContainerComposition**shinks in width to contain its content. When**ExtendToFullWidth**is**true**, width of**ContainerComposition**extends to the**ViewSize**when the total width of its content doesn't exceed the width of the control.
|
||||
|
||||
This feature is very useful when you want to create a layout with limited width but unlimited height. Just set **ExtendToFullWidth** to **true** and **HorizontalAlwaysVisible** to **false**, with correct compositions to make content fills the whole space in width but has a very small minimum width (e.g. fill things in a **\<Flow/\>**, or multiple **\<Flow/\>** in a vertical **\<Stack/\>**). When **\<ScrollContainer\>** shrinks in width, its content reorganizes to shrink in width but grow in height.
|
||||
This feature is very useful when you want to create a layout with limited width but unlimited height. Just set**ExtendToFullWidth**to**true**and**HorizontalAlwaysVisible**to**false**, with correct compositions to make content fills the whole space in width but has a very small minimum width (e.g. fill things in a**\<Flow/\>**, or multiple**\<Flow/\>**in a vertical**\<Stack/\>**). When**\<ScrollContainer\>**shrinks in width, its content reorganizes to shrink in width but grow in height.
|
||||
|
||||
**ExtendToFullHeight** works in the same way.
|
||||
**ExtendToFullHeight**works in the same way.
|
||||
|
||||
## Sample
|
||||
|
||||
- Source code: [control_container_scrollcontainer](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_container_scrollcontainer/Resource.xml) - 
|
||||
|
||||
- Source code:[control_container_scrollcontainer](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_container_scrollcontainer/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,18 +1,35 @@
|
||||
# \<Tab\> and \<TabPage\>
|
||||
|
||||
- **\<Tab/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiTab* - **Template Tag**: \<TabTemplate/\> - **Template Name**: Tab
|
||||
|
||||
- **\<TabPage/\>** - **C++/Workflow**: (vl::)presentation::controls::GuiTabPage* - **Template Tag**: \<ControlTemplate/\> - **Template Name**: CustomControl
|
||||
- **\<Tab/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiTab*
|
||||
- **Template Tag**: \<TabTemplate/\>
|
||||
- **Template Name**: Tab
|
||||
|
||||
When a **\<Tab/\>** is deleted, all **\<TabPage/\>** in its **Pages** will also be deleted.
|
||||
|
||||
When a **\<TabPage/\>** is activated, only content of this tab page is visible in the **\<Tab/\>**. But inactivated pages still limit the minimum size of the **\<Tab/\>**. The only exception is when an inactivated page has never become activated, since its content has never been rendered, the minimum size of that page is never calculated.
|
||||
- **\<TabPage/\>**
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiTabPage*
|
||||
- **Template Tag**: \<ControlTemplate/\>
|
||||
- **Template Name**: CustomControl
|
||||
|
||||
When a**\<Tab/\>**is deleted, all**\<TabPage/\>**in its**Pages**will also be deleted.
|
||||
|
||||
When a**\<TabPage/\>**is activated, only content of this tab page is visible in the**\<Tab/\>**. But inactivated pages still limit the minimum size of the**\<Tab/\>**. The only exception is when an inactivated page has never become activated, since its content has never been rendered, the minimum size of that page is never calculated.
|
||||
|
||||
## Patterns
|
||||
|
||||
**\<Tab/\>** is a container with multiple labeled pages, each page is a **\<TabPage/\>**. Typically they are created in this pattern: ``` <Tab> <att.Pages> <TabPage Text="Title" Alt="X"> ... </TabPage> ... </att.Pages> </Tab> ``` If an **ALT** sequence is assigned to a tab page, the page will be selected and shown to the user when the **ALT** sequence is hit. Please check out [ this tutorial project ](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Controls/Animation/UI/Resource.xml) for more details.
|
||||
**\<Tab/\>**is a container with multiple labeled pages, each page is a**\<TabPage/\>**. Typically they are created in this pattern:
|
||||
```
|
||||
<Tab>
|
||||
<att.Pages>
|
||||
<TabPage Text="Title" Alt="X"> ... </TabPage>
|
||||
...
|
||||
</att.Pages>
|
||||
</Tab>
|
||||
```
|
||||
If an**ALT**sequence is assigned to a tab page, the page will be selected and shown to the user when the**ALT**sequence is hit. Please check out[this tutorial project](https://github.com/vczh-libraries/Release/blob/master/Tutorial/GacUI_Controls/Animation/UI/Resource.xml)for more details.
|
||||
|
||||
**\<TabPage/\>** is also a **GuiInstanceRootObject**, which means it could also be a base class of an **\<Instance/\>**. It is very useful when you want to put a tab page in a single file, or create components that just for this tab page and other part of the code cannot access these components. Please check out [ this tutorial page ](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/ListControls) for more details.
|
||||
**\<TabPage/\>**is also a**GuiInstanceRootObject**, which means it could also be a base class of an**\<Instance/\>**. It is very useful when you want to put a tab page in a single file, or create components that just for this tab page and other part of the code cannot access these components. Please check out[this tutorial page](https://github.com/vczh-libraries/Release/tree/master/Tutorial/GacUI_Controls/ListControls)for more details.
|
||||
|
||||
## \<Tab\> Properties
|
||||
|
||||
@@ -20,25 +37,27 @@ When a **\<TabPage/\>** is activated, only content of this tab page is visible i
|
||||
|
||||
The default value for this property is empty.
|
||||
|
||||
This property is an observable collection. When tab pages are added to **Pages**, labels displaying their **Text** property will also be added to the tab control.
|
||||
This property is an observable collection. When tab pages are added to**Pages**, labels displaying their**Text**property will also be added to the tab control.
|
||||
|
||||
If a tab page is added to **Pages** when it is empty, it automatically becomes activated, and **SelectedPage** is set to this tab page. If a tab page is removed from **Pages** and cause it to become empty, **SelectedPage** will also become **null**.
|
||||
If a tab page is added to**Pages**when it is empty, it automatically becomes activated, and**SelectedPage**is set to this tab page. If a tab page is removed from**Pages**and cause it to become empty,**SelectedPage**will also become**null**.
|
||||
|
||||
### SelectedPage (SelectedPageChanged)
|
||||
|
||||
This property is **null** only when **Pages** is empty.
|
||||
This property is**null**only when**Pages**is empty.
|
||||
|
||||
This property represents the current activated tab page. Only tab pages in **Pages** could be assigned to this property.
|
||||
This property represents the current activated tab page. Only tab pages in**Pages**could be assigned to this property.
|
||||
|
||||
## \<TabPage\> Properties
|
||||
|
||||
### OwnerTab
|
||||
|
||||
This property returns the **\<Tab/\>** that owns this tab page.
|
||||
This property returns the**\<Tab/\>**that owns this tab page.
|
||||
|
||||
When a tab page is added to a tab's **Pages**, **OwnerTab** becomes this tab control. When a tab page is removed from a tab's **Pages**, **OwnerTab** becomes **null**.
|
||||
When a tab page is added to a tab's**Pages**,**OwnerTab**becomes this tab control. When a tab page is removed from a tab's**Pages**,**OwnerTab**becomes**null**.
|
||||
|
||||
## Sample
|
||||
|
||||
- Source code: [control_basic_window](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_window/Resource.xml) - 
|
||||
|
||||
- Source code:[control_basic_window](https://github.com/vczh-libraries/Release/blob/master/SampleForDoc/GacUI/XmlRes/control_basic_window/Resource.xml)
|
||||
- 
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
# \<DocumentLabel\> and \<DocumentTextBox\>
|
||||
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiDocumentLabel* - **Template Tag**: \<DocumentLabelTemplate/\> - **\<DocumentLabel/\>** - **Template Name**: DocumentLabel - **\<DocumentTextBox/\>** - **Template Name**: DocumentTextBox
|
||||
|
||||
The control template doesn't need to care about rendering characters. When it is installed to the control, a fully managed **GuiDocumentElement** will be installed to the **ContainerComposition** of the control template.
|
||||
- **C++/Workflow**: (vl::)presentation::controls::GuiDocumentLabel*
|
||||
- **Template Tag**: \<DocumentLabelTemplate/\>
|
||||
- **\<DocumentLabel/\>**
|
||||
- **Template Name**: DocumentLabel
|
||||
- **\<DocumentTextBox/\>**
|
||||
- **Template Name**: DocumentTextBox
|
||||
|
||||
**\<DocumentLabel/\>** and **\<DocumentTextBox/\>** don't provide any scroll bar. When a paragraph is too long to display, auto line-wrapping is automatically done so that the horizontal scroll bar is always not needed. Height of these controls will grow to display the whole document. But such default behavior can be changed.
|
||||
The control template doesn't need to care about rendering characters. When it is installed to the control, a fully managed**GuiDocumentElement**will be installed to the**ContainerComposition**of the control template.
|
||||
|
||||
There is no functionality difference between **\<DocumentLabel/\>** and **\<DocumentTextBox/\>**. **\<DocumentLabel/\>** is expected to look like a **\<Label/\>**. **\<DocumentTextBox/\>** is expected to look like **\<SinglelineTextBox/\>**.
|
||||
**\<DocumentLabel/\>**and**\<DocumentTextBox/\>**don't provide any scroll bar. When a paragraph is too long to display, auto line-wrapping is automatically done so that the horizontal scroll bar is always not needed. Height of these controls will grow to display the whole document. But such default behavior can be changed.
|
||||
|
||||
There is no functionality difference between**\<DocumentLabel/\>**and**\<DocumentTextBox/\>**.**\<DocumentLabel/\>**is expected to look like a**\<Label/\>**.**\<DocumentTextBox/\>**is expected to look like**\<SinglelineTextBox/\>**.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user