TTabSet tab Order....Different At Run Time Than Design Time - delphi

I am running Lazarus 0.9.30.2.
I have a TForm on which there is a TPageControl. Within the TPageControl there is a series of TTabSheets. At runtime the order of the TTabSheets differs from design time (see picture).
The order in design time is what I want to see at runtime, at least for the very first time the form is displayed. Why does the order change at run time and is there a way to control this?

#TLama is correct that this is related to way the Windows tab control behaves when in multi-line view. The behaviour you are observing is related to the way selection is handled for multi-line tabs. When you select a tab it is always shown in the bottom row because the visual cue to indicate which tab is selected can only really work for tabs in the bottom row.
Given that constraint the control simply has to rearrange rows of tabs as you modify the selected tab. It's astoundingly confusing for the user. Good UI design never has UI elements changing position like this.
Clearly what is happening here is that the rearrangement is happening at runtime when the form is first shown and for whatever reason this is resulting in a different arrangement from the design time arrangement. Given that the user can arrange the rows in any order just by selecting them I'm not sure you should worry about what order the rows appear in.
If you are dead set on forcing a particular arrangement when the form first shows you can add code like this to a OnCreate handler for the form:
PageControl1.ActivePage := TabSheet9;
PageControl1.ActivePage := TabSheet5;
PageControl1.ActivePage := TabSheet1;
Best practise for UI design is to avoid multi-line tab controls and I urge you to attempt to re-design your UI that way.

Related

TRadioButton dropped on TListBoxItem behaves erratically when scrolled

I am trying to implement a Firemonkey TListbox that has a number of TListBoxItems. On one of the TListBoxItems I have placed a number of TRadioButtons by simply dropping them on the TListBoxItem at design time. When the application is run the visual appearance of the buttons is erratic when the TListBoxItem is scrolled off the screen and back on.
Another TListBox question here at StackOverflow makes the point that a TListBox does not host any item other than a TListBoxItem. That being said, there seems to be no such restriction that I can find about a TListBoxItem. I have routinely placed TEdit, TLabel and TComboBox components in this manner without difficulty.
To duplicate the condition start a new Firemonkey desktop application; drop a TListBox on the form and set it to alClient; populate the TListBox with a number of TListBoxItems; set the heights of the TListBoxItems or Form so that when run, you are able to scroll the TListBox; drop three TRadioButtons on the topmost TListBoxItem; set the GroupName for all the TRadioButtons to the same name; run the application; select a TRadioButton so that it appears selected; scroll the TListBox so that the TListBoxItem containing the buttons scrolls off the form; scroll back; continue selecting different TRadioButtons and scrolling until anomalies are observed.
Questions: First and probably most important, am I permitted to simply drop components on a TListBoxItem at design time? Has my previous success with this technique been simply accidental?
Second and also of importance for an application I'm working on, if this is NOT a viable approach to my UI, can anyone suggest better approaches?
TIA
I entered a Report at Embarcadero's Quality Central and after a few exchanges with Tomohiro-san along with Marcus Adams suggestion that the problem is related to scrolling came up with the following:
Tracking through the various cases mentioned it appears that there are a number of other cases that are related to this one because of the use of scrolling. When an item is scrolled off the screen and then scrolled back the system apparently reapplies the styles to the items being returned to visibility. At least, in the few cases I have traced that seems to be the case. It is on this reapplication of style and rendering that the problem seems to occur. In my own examples I have added a button that displays the IsChecked property for the controls and the rendering does not reflect the property correctly in all cases, suggesting that it is the style/rendering that is causing the issues.
The related issues I was able to find are:
QC 120593
QC 117381
QC 119638
QC 117658
I'm waiting for a resolution.
I ran into the same problem. I found no solution, but as a work-around, I ended up just replacing the radio buttons with check boxes and adding code so that they behaved in a similar manner to Radio buttons. E.g., only allowing one of a group of check boxes to be selected...

hide UI components at RUN TIME , design issue

on a form I need a first set of UI controls at process start, later I only need a second set of components. I put the set for process set #1 on a first panel , after finish process step #1 I start to hide panel #1, is ther any better way from UI design guide lines ?
I would use Frames instead of Panels. You can design Frames at design-time just like Forms, and then create instances of your Frames at run-time as needed. So create your first Frame (you can even place it on the Form at design-time) and then at run-time, when ready you can destroy the first Frame instance and create an instance of the second Frame.
Using panels like you describe is a very common and very respectable way to proceed. Nothing wrong with doing it that way.
Another often used idiom is a page control with hidden tabs. So, make a page control. Add two tab sheets. Set TabVisible to False for both tab sheets. Then at run time set the ActivePage property of the page control to specify which page is shown to the user.
The page control approach is really rather similar to using panels. It's perhaps marginally easier to work with at design time, but much comes down to personal preference.

FireMonkey grid with different controls in same column

What can you do if you want different cell controls in the same column of a grid in FireMonkey.
The cell control seems to belong to the column, but there are situations (like the property editor), where some rows need a checkbox while other rows need a combobox or an edit control.
Thanks in advance.
The following steps should get you up and running:
Create a style, add to it the controls you want to show (i.e. a TCheckbox, a TCombobox and a TEdit). Add these within a TLayout, and set each controls StyleName to something memorable.
In your cells ApplyStyle use FindStyleResource to extract the controls you added above using their StyleNames.
When the grid calls your cell's SetData method, you need to set the Visible property for each control so only the appropriate one is shown. If you can't determine this from the data passed in, add an event handler to the cell to get the data.
You'll need to sort out the keyboard handling, which gets pretty messy. If memory serves, you need to pass keys from the grid/cell to the control (or or is it trap movement keys from the controls and pass them to the grid? Sorry if I forget exact detail).
Sorry I can't give a more detailed answer, but covering this completely would take a whole series of blog posts.
Use a style - set the cell style when you set the cell data - then us the onapplystyle event to do anything clever you require with the newly styled cell.
This way you can add what controls you need to the style and then access the controls (to set events etc) with the onapplystyle.
Hint - FindStyleResource is your friend here :-)
I have also needed a property editor and looked for a way hosting different cell types in one column. Using different styles for each row may be a solution as suggested above, but since Firemonkey grid doesnt reserve any cell control for a specific row, each time the cell control would be shown on the row, the true style would be applied to it. This is not a big problem for a static property editor, however for a real grid which has got may rows and different cell types in each row a diferent strategy is needed. So I came up with a different solution, I considered cell type proxies between TColumn and cell controls, so that each cell proxy will reserve the cell controls that is responsible for. First of all, I have a new TColumn (TvariantColumn) which is responsible for the top strategy.
vColumn := TVariantColumn.Create(Self);
vColumn.Header := 'Variant Column';
vColumn.OnGetCellProxyIndex := GetCellProxyIndex;
Grid1.AddObject(vColumn);
Then create any proxies like
vColumn.NewCellProxy(TTextProxy);
vColumn.NewCellProxy(TColorComboProxy);
vColumn.NewCellProxy(TComboColorProxy);
You can also handle Proxy specific jobs after you create it, like
with TProgressProxy(vColumn.NewCellProxy(TProgressProxy)) do //4
begin
Min := 0;
Max := 100;
end;
with TPopUpProxy(vColumn.NewCellProxy(TPopupProxy)) do //5
begin
Items.Add('Istanbul');
Items.Add('Paris');
Items.Add('NewYork');
end;
I have blogged my method in my website and published a detailed article where you can find more about the subject.

Caption for TTabControl

I'm looking for a way of implementing a sort of inset caption before a set of tabs, something like this:
The tab set is not supposed to be multi-line, will only be horizontal and laid out at the top. However it should be correctly scrollable when there are too many tabs.
I fear I'm going to be restricted here with regard to using third-party controls, but I could use subclassing on the standard TTabControl to add the necessary changes to the standard looks and behaviour. (I don't need it to be TPageControl, because it's only the specific arrangement of the tabs that I am interested in.)
Maybe there's some way of implementing this with craftily arranged combination of standard controls, which, despite my endevours, has escaped me.
Basically, any ideas or pointers are welcome.
Oh, and additional requirement is, it should blend well with desktop themes.
Granted some time has passed, but I recently needed this style and found you can do it with the TMS Software TAdvOfficePager. It has a property FixedTabs, which I set to 1 in this case. It also has an OnChanging event where you can prevent access to a tab, in this case I used AllowChange := (ToPage > 0); Lastly, I set the first tab to disabled.
Then just style the first tab different than the rest and you can have something like this:
Have you tried to make the first tab to be the caption you want.
With some additional logic you can restrict the selection of this tab.
I don't know if you can control the style of each tab individually to make the first one look as it is not the tab.
Here is crafty arrangement of controls that will work. I have done this sort of thing in the past. Best of all it automatically handles scrolling of tabs.

Frame behavior in Delphi application issue

I have an application that uses a frame extensively and needs to hide/show certain buttons depending on which form is active at the time. In order to keep the buttons neat and organized appropriately, I have put them on panels and show or hide the panels as needed for each form. My problem is when each form is initially created, the panels on the frame are out of order even though I am explicitly telling them which order to put themselves into. After I hide and re-show the form, the panels are in the correct order. Any suggestions on how to keep them in the proper order from the very beginning?
Instead of giving the panels explicit positions, try giving them alignments. They tend to stick better than way, and they do a better job of resizing if you resize the form.
You can also try using a stackpanel (or was it flowpanel?) as parent for the panels. Then you will have a order instead of a position to manipulate.
Maybe you can have a look at the DevExpress LAyoutControl? It helps us creating interfaces that always look good, no matter if we show or hide certain groups / panels. It even allows for run-time customization of the interface, if you want that!
You may try to organize them by coordinates i.e.: setting Top and Left. Unless your panels are aligned, this will always work (but it takes bit lot of work).
I had this problem and I found that the solution was to do this in FormCreate (or in a CMShowingChanged method of your frame):
MyPanel1.Align := alNone;
MyPanel2.Align := alNone;
MyPanel1.Align := alBottom;
MyPanel2.Align := alBottom;
Restore in the order that you need - this seemed to sort out the order visually.

Resources