Genexus: access sub grid's data when clicking its control - genexus

I have two SDT collections with the following structures:
Areas (collection)
L Area (structure)
L Codigo (char 20)
Orden (num 2.0)
Rojo (num 3.0)
Verde (num 3.0)
Azul (num 3.0)
Mostrar (char 10)
Camas (SDT Camas)
Camas (collection)
L Cama (structure)
L Id (num 8.0)
Paciente (num 8.0)
Edad (char 10)
Nombre (char 30)
Comienzo (datetime)
Duracion (char 10)
Evento (num 8.0)
Area (char 20)
Cama (char 20)
Sector (char 20)
Then, I have a Web Panel with one Free Style Grid based on Areas SDT collection through an &areas variable. Inside that Grid I have a normal Grid based on the Camas SDT collection through &areas.item(0).Camas.
This works well enough. The panel has a block for each area thanks to the Free Style Grid, and inside each block I have a list of each area's 'camas' (beds) through the normal Grids.
Now I need to make the Nombre control for each sub grid clickable and make so the data in Paciente is saved to the WebSession of the user. I thought I could use &areas.CurrentItem.Camas.CurrentItem.Paciente but that doesn't work.
What would I need to do to access a sub grid's data when clicking its control?
I'm using Genexus 16 btw.

Managed to get the behavior I wanted.
Instead of basing the subgrid on the &areas.item(0).Camas collection, I removed the reference to the collection and used a &cama variable based on the Camas.Cama substructure for all items inside the grid. I also added a &paciente variable to the grid. Then, I just loaded each &cama while looping inside the &areas.CurrentItem.Camas collection, and gave &paciente the same value as '&cama.Paciente'.
After that, I can access the data I wanted through the &paciente variable when executing the click event of any control inside the sub grid.
Code:
Event GridAreaCamas.Load
For &cama in &areas.CurrentItem.Camas
&paciente = &cama.Paciente
GridAreaCamas.Load()
EndFor
EndEvent
Event ctlPacienteNombreCompleto.Click
&webSession.Set(!"paciente_seleccionado", &paciente.ToString())
EndEvent

Related

I found GetCheckedItems() function that is could know how items checked included child items in Tree Control

I know what is the shift and bit operator but what mean this code? I don't understand well.
Please explicate me very easy.
UINT state = (tree.GetItemState(item, TVIS_STATEIMAGEMASK) >> 12) & 15;
Below is the original code:
void GetCheckedItems(const CTreeCtrl& tree, CArray<HTREEITEM>
*checkedItems, HTREEITEMstartItem=NULL)
{
if (startItem == NULL)
startItem = tree.GetRootItem();
for (HTREEITEM item = startItem; item != NULL; item =
tree.GetNextItem(item, TVGN_NEXT))
{
// figure out if this item is checked or not
UINT state = (tree.GetItemState(item, TVIS_STATEIMAGEMASK) >> 12) &
15; // i Wonder this ( shift and bit operator )
if (state == 2)
checkedItems->Add(item);
// deal with children if present
HTREEITEM child = tree.GetNextItem(item, TVGN_CHILD);
if (child != NULL)
GetCheckedItems(tree, checkedItems, child);
}
}
In short: (state >> 12) & 15 moves bits 12 through 15 down to bits 0 through 3, and clears everything starting from bit 4 upwards.
In context of tree-view controls this is meaningful for application-defined image states. As explained under Tree-View Item States Overview:
A state image is displayed next to an item's icon to indicate an application-defined state. State images are contained in a state image list that is specified by sending a TVM_SETIMAGELIST message. To set an item's state image, include the TVIS_STATEIMAGEMASK value in the statemask member of the TVITEM structure. Bits 12 through 15 of the structure's state member specify the index in the state image list of the image to be drawn.
The check state of a tree-view control's item is stored in the item state. By convention, the image at index 0 requests no state image, index 1 is the unchecked state, and index 2 the checked state.
Masking out the state image index concerned with the check state of an item, and comparing it against the value 2 thus determines whether a tree-view item's state is checked.

HandsonTable not rendering all rows

HandsonTable is not rendering all rows - it loads only part of all rows. But when I do Ctrl+A and paste into Excel I see all the rows. Why is Handsontable not displaying all the rows?
<hot-table col-headers="true" row-headers="true" datarows="data" context-menu width="1080">
<hot-column ng-repeat="column in columns" data="{{column.data}}"></hot-column>
</hot-table>
To render all rows, just set renderAllRows: true
The current answer does not answer the original question.
Handsontable does not render all cells at once because it is designed to be efficient for very large data sets. It does this using virtual rendering, dynamically modifying the DOM to include only the cells at the scroll position.
The rows virtual rendering can be disabled by setting renderAllRows: true, as described in the docs: "If typed true then virtual rendering mechanism for handsontable will be disabled." Although it will then not be as efficient for large data sets.
You can also change the number of pre-rendered rows and columns instead of rendering them all. From the performance tips,
You can explicitly specify the number of rows and columns to be rendered outside of the visible part of the table. In some cases you can achieve better results by setting a lower number (as less elements get rendered), but sometimes setting a larger number may also work well (as less operations are being made on each scroll event). Tweaking these settings and finding the sweet spot may improve the feeling of your Handsontable implementation.
This is done by setting viewportRowRenderingOffset and viewportColumnRenderingOffset in the handsontable options. These are by default set to auto which lets handsontable try to find the best value, but may be provided an integer value (e.g. viewportRowRenderingOffset: 70, viewportColumnRenderingOffset: 70).
I had the same problem (using HandsOnTable 6.2.1 and the old AngularJS) and customers would start complaining about not being sure if they were at the end of the table or not.
I was able to create two buttons linked to the functions 'scrollToBeginning' and 'scrollToEnd'. This way the user is sure to be at the last line. Three things specific about my answer:
I expose the functions to the DOM using $scope;
I have an object 'goToLine' holding 3 properties (scrollingToEnd: boolean, row: number, col: number), it is used in other functions not posted here;
I have a list of ID referencing HandsOnTable objects stored in $scope.hots.
Here is my raw solution, feel free to adapt / enhance:
$scope.stopScrollingToEnd = function () {
$scope.goToLine.scrollingToEnd = false;
};
$scope.scrollToBeginning = function (goToLine) {
$scope.stopScrollingToEnd();
const hot = $scope.hots[goToLine.id];
hot.scrollViewportTo(0, 0);
};
/**
* Scroll to the end of the List Element.
* We need this functionality because of a bug in HandsOnTable related to its Virtualization process.
* In some cases (complex table), when manually scrolling, the max row is wrong, hence causing major confusion for the user.
* #param {*} goToLine
* #returns
*/
$scope.scrollToEnd = function (goToLine) {
// We scroll to the first line before going to the last to avoid the bug and being sure we get to the last line
$scope.scrollToBeginning(goToLine);
const hot = $scope.hots[goToLine.id];
var numberOfRows = hot.countRows();
// This variable is used to repeat the scrollViewportTo command.
// It is built using the length of `numberOfRows`.
var repeat = numberOfRows ? 1 * Math.ceil(Math.log10(numberOfRows + 1)) : 1;
// Used in other goTo function to avoid conflict.
$scope.goToLine.scrollingToEnd = true;
// FIXME : not supposed to call scrollViewportTo several times... => fixed in recent versions of HandsOnTable ?
for (let n = 0; n < repeat; n++) {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
setTimeout(function () {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
hot.scrollViewportTo(numberOfRows - 1, 0);
}, 500);
}
};

Creating a table using Win32 API

I've been searching the net for different things about the win32 API, but it seems all information on it is rather sparse.
I am looking to create a simple window that shows a list of items, however I want to display different columns of data for each item, in a table-style format, where the user could perhaps be allowed to resize the different column widths.
If at all possible, I'd like to also be able to change the background colors of different rows, in the code, between just a general white, red, yellow, or green.
And the user would also be allowed to right click different rows, and be able to call a function on them, or copy the data to the clipboard (but that part is a different story).
Now, I've found list-viewer objects(?) that can be placed in the window, buttons, and right-click menus... but I cannot figure out how to do a table, using the Win32 API. I haven't even really read up on background colors for anything other than the window itself, either.
Is there a different, better framework I should use for this, or are there some functions or items that I've been missing? All help or guidance on the idea would be appreciated...
I'm using MSVC++ to do... everything that I'm working on.
Using the windows API and the standard control ListView you can do a table using the style LVS_REPORT
documentation link - unfortunatelly with no code :( -
About List-View Controls
I've found this good article Windows Programmierung: List View
the explanation is in german language but a google translation together with the code should be enough to understand it. From the article, to create the window:
#include "commctrl.h"
InitCommonControls();
hwndList = CreateWindow(WC_LISTVIEW, "",
WS_VISIBLE|WS_BORDER|WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
10, 10, 300, 100,
hWnd, (HMENU)ID_LIST, hInst, 0);
then it is explained how to create the columns in the method
int CreateColumn(HWND hwndLV, int iCol, char *Text, int iWidth)
how to insert an item (one column)
int CreateItem(HWND hwndList, char *Text)
or insert item with two columns
int Create2ColItem(HWND hwndList, char *Text1, char *Text2)
etc...
Windows provides a fairly basic collection of built-in controls, listed here.
If you want something more sophisticated your options are:
Code it yourself. You have to paint it yourself, handle all the user-interaction, the scrolling, etc. This is a big job.
Find an existing implementation.
Abandon VC++ and use WinForms or WPF.
If you're stuck with VC++, The Grid Control and The Ultimate Grid are MFC-based.
If you're not using MFC there's BABYGRID or The Win32 SDK Data Grid.
If none of them suit, you'll have more luck searching for "grid" than "table".
For Listview examples, nothing beats the clarity of the Classic Sample!
In the meantime, Google Translate along with Unicode + tiny modifications to the rescue for #Alejadro's German link for the Listview- there's no direct translation on offer from search results as the page doesn't contain the appropriate meta tag. Snipped a little for brevity:
Subsequent changes of styles
The style of a ListView can be changed after creation. For this the functions GetWindowLong and SetWindowLong are used. About masks different styles can be defined.
Mask.................................Masked Styles:
LVS_TYPEMASK..............LVS_ICON, LVS_LIST, LVS_REPORT and LVS_SMALLICON
LVS_ALIGNMASK.............LVS_ALIGNLEFT and LVS_ALIGNTOP
LVS_TYPESTYLEMASK...LVS_ALIGNLEFT and LVS_ALIGNTOP but also VS_NOCOLUMNHEADER and LVS_NOSORTHEADER
For the following sequence, dwView contains the style to use, such as LVS_REPORT or LVS_ICON.
DWORD dwStyle = GetWindowLong(hwndLV, GWL_STYLE); // get current style
if ((dwStyle & LVS_TYPEMASK)! = dwView) // only on change
SetWindowLong(hwndLV, GWL_STYLE, (dwStyle & ~ LVS_TYPEMASK) | dwView); }
Control of the ListView control
Generating a list
A list view is created with the CreateWindow function. The window class uses the constant WC_LISTVIEW. To do this, the common control header file must be included.
#include "commctrl.h"
InitCommonControls();
hwndList = CreateWindow(WC_LISTVIEW, "",
WS_VISIBLE | WS_BORDER | WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
10, 10, 300, 100,
hWnd, (HMENU) ID_LIST, hInst, 0);
In the dialog, it is simply defined in the resource.
If there are unresolved externals, you should check whether the library for the Common Controls (comctl32.lib) is included.
Columns of the ListView
Before something can be inserted in a REPORT, the columns must be defined. A column is described by the structure LVCOLUMN. The following routine creates a column.
int CreateColumn(HWND hwndLV, int iCol, char * text, intwidth)
{
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = iWidth;
lvc.pszText = text;
lvc.iSubItem = iCol;
return ListView_InsertColumn(hwndLV, iCol, & lvc);
}
The columns can be modified by messages to the ListView or by calling macros that will ultimately execute a SendMessage.
Message Macro call Function
LVM_INSERTCOLUMN ListView_InsertColumn(HWND, int, LVCOLUMN * ) Insert column
LVM_DELETECOLUMN ListView_DeleteColumn(HWND, int) Delete column
LVM_GETCOLUMN ListView_GetColumn(HWND, int, LVCOLUMN * ) Get properties of the column
LVM_SETCOLUMN ListView_SetColumn(HWND, int, LVCOLUMN * ) Change properties of the column
LVM_GETCOLUMNWIDTH ListView_GetColumnWidth(HWND, int) Determine column width
LVM_SETCOLUMNWIDTH ListView_SetColumnWidth(HWND, int, int) Set column width
Insert a line
An element of the ListView is described by the structure LVITEMW (see below). Each element can be represented as an ICON, SMALLICON, LIST element or as the left column of a REPORT line.
int CreateItem(HWND hwndList, wchar_t * text)
{
LVITEMW lvi = {0};
lvi.mask = LVIF_TEXT;
lvi.pszText = text;
return ListView_InsertItem(hwndList, & lvi);
}
The mask field determines which elements of the LVITEMW structure are really used. Since it often makes sense to keep a pointer to the memory object that holds the data behind the object, the lParam field is useful. In order for this to be used, LVIF_TEXT | LVIF_PARAM must be set as a mask.
The constants of mask and the fields that enable them:
LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
LVIF_STATE state
LVIF_TEXT pszText
The further columns of a report
The element itself is always left in the report view and is selectable. To fill more columns, a text is added to the item.
int Create2ColItem(HWND hwndList, wchar_t * Text1, wchar_t * Text2)
{
LVITEMW lvi = {0};
int Ret;
// Initialize LVITEMW members that are common to all items.
lvi.mask = LVIF_TEXT;
lvi.pszText = Text1;
Ret = ListView_InsertItem(hwndList, & lvi);
if (Ret >= 0)
{
ListView_SetItemText(hwndList, Ret, 1, Text2);
}
return Ret;
}
The above Create2ColItem is best demonstrated by something along the line of the following statements:
LVHwnd = Your_Create_LV_Routine();
if (LVHwnd)
{
CreateColumn(LVHwnd, 0, ptrColHeaderString1, iColSize1);
CreateColumn(LVHwnd, 1, ptrColHeaderString2, iColSize2);
Create2ColItem(LVHwnd, ptrItemText1, ptrItemText2);
}
The structure LVITEMW
The structure LVITEMW (in CommCtrl.h) describes an element of the ListView. The most important elements are briefly described here. First the definition:
typedef struct tagLVITEMW
{
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPWSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300) //historical note for IE3 users!
int iIndent;
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
int iGroupId;
UINT cColumns; // tile view columns
PUINT puColumns;
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
int* piColFmt;
int iGroup; // readonly. only valid for owner data.
#endif
} LVITEMW, *LPLVITEMW;
The LVM_GETITEMW and LVM_SETITEMW messages change the attributes of an element. As a parameter, you get a pointer to a LVITEMW structure next to the HWND of the ListView, which must be filled in advance.
The structural elements in detail:
Mask:
Specifies which elements are used. A combination of the following flags is possible:
LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
LVIF_STATE state
LVIF_TEXT pszText
iItem
Index (0-based) of the item to which the structure relates.
iSubItem
Index (1-based) of the subitem to which the structure relates. 0 if the structure refers to an item instead of a subitem.
pszText
points to a null-terminated string. If the value is LPWSTR_TEXTCALLBACK, it is a callback item. If this changes, pszText must be set to LPSTR_TEXTCALLBACK and the ListView informed by LVM_SETITEMW or LVM_SETITEMTEXT.
pszText must not be set to LPWSTR_TEXTCALLBACK if the ListView has the style LVS_SORTASCENDING or LVS_SORTDESCENDING.
cchTextMax
Size of the buffer when the text is read.
iImage
Index of the icon of this element from the image list.
lParam
32-bit value that is specific to this element.
Actions with elements
LVM_INSERTITEM Insertion of an element
LVM_DELETEITEM Delete an element
LVM_DELETEALLITEMS Delete all elements
LVM_GETITEMW Read properties of the element
LVM_GETITEMTEXT Read text of the element
LVM_SETITEMW change
LVM_SETITEMTEXT Change to the text
Before inserting multiple items, an LVM_SETITEMCOUNT message will be sent to the ListView indicating how many items will ultimately be contained. This allows the ListView to optimize its memory allocation and release. How many elements a ListView contains can be determined with LVM_GETITEMCOUNT.
Editing selected elements
int Pos = -1;
LVITEMW Item;
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED);
while (Pos> = 0)
{
Item.iItem = Pos;
Item.iSubItem = 0;
ListView_GetItem(hwndList, & Item);
TuWasMitElement((Element Type * ) Item.lParam);
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED);
}
Events
The ListView sends WM_NOTIFY messages to the parent window. The code can take the following values:
Message............ Description
LVN_BEGINDRAG.............Start a drag-and-drop action
LVN_BEGINRDRAG..........Start a drag-and-drop action with the right mouse button
LVN_BEGINLABELEDIT....Start editing a label
LVN_ENDLABELEDIT.......End edit of a label
LVN_DELETEITEM..........Reports that the item is deleted
LVN_DELETEALLITEMS..Reports that all items are deleted
LVN_COLUMNCLICK......Indicates that the user clicked in the header of a report display
LVN_GETDISPINFO.......The control requests information about the presentation from the parent window
LVN_SETDISPINFO.......The information of the parent window for the item must be renewed
LVN_INSERTITEM..........Indicates the insertion of an item
LVN_ITEMCHANGED.....Indicates that an item has been changed
LVN_ITEMCHANGING....Indicates the intended change of an item
LVN_KEYDOWN.............Key was pressed
Editing the labels
The list view must have been created using the LVS_EDITLABELS style. Then a label can already be clicked on and inputs are accepted. However, the input is discarded immediately afterwards. To allow changes in the label, you just need to catch the WM_NOTIFY and return TRUE. In order to access the entered text in between, access is made to the text of the item. The example shows the input in a message box.
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_ENDLABELEDIT:
pItem = (NMLVDISPINFO) lParam;
MessageBox (hWnd, pItem-> item.pszText, "entry", MB_OK);
return TRUE;
If editing was aborted, the pszText element will be 0.
If you want to prevent editing, the message LVN_BEGINLABELEDIT is caught and returned TRUE. Here, too, the item can be accessed in the same way via lParam and thus, for example, a certain item group can be excluded.
Click on the column header in the ListView
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_COLUMNCLICK:
ColumnNr = ((LPNMLISTVIEW) lParam) -> iSubItem;
.....
Selection Event
The LVN_ITEMACTIVATE event is sent when the user activates an item. As with the other ListView events, it achieves the window function as part of a WM_NOTIFY message.
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_ITEMACTIVATE:
HWND hwndFrom = (HWND) ((LPNMHDR) lParam) -> hwndFrom;MarkedItemIndex =
ListView_GetNextItem(hwndFrom, -1, LVNI_SELECTED);
.....
The LVM_GETSELECTEDCOUNT message can be used to determine how many items have been activated. The LVM_GETNEXTITEM message is sent with the LVNI_SELECTED attribute and all items have been edited.

Swapping property values between objects

I have created two textboxes via annotation(.) in a figure. Most of their properties have been defined; and the callback function enables drag and drop motion in the window. I created a uicontextmenu for the boxes. On right click a list of functions can be chosen from for subsequent action.
One of the actions I am trying to add involves swapping strings between the two boxes. I need to get the string of the box I currently right-clicked, which should swap with the string in the box I subsequently left-click. Can I get advice on how to go about extending the uimenu function so that it registers the subsequent left-click?
You will need to manually store the last clicked box. If you are using GUIDE to design your GUI, use the handles structure which gets passed around to callback functions. Otherwise if you programmatically generate the components, then nested callback functions have access to variables defined inside their enclosing functions.
EDIT
Here is a complete example: right-click and select "Swap" from context menu, then choose the other textbox to swap strings with (left-click). Note that I had to disable/enable the textboxes in-between the two steps to be able to fire the ButtonDownFcn (see this page for an explanation)
function myTestGUI
%# create GUI
hLastBox = []; %# handle to textbox initiating swap
isFirstTime = true; %# show message box only once
h(1) = uicontrol('style','edit', 'string','1', 'position',[100 200 60 20]);
h(2) = uicontrol('style','edit', 'string','2', 'position',[400 200 60 20]);
h(3) = uicontrol('style','edit', 'string','3', 'position',[250 300 60 20]);
h(4) = uicontrol('style','edit', 'string','4', 'position',[250 100 60 20]);
%# create context menu and attach to textboxes
hCMenu = uicontextmenu;
uimenu(hCMenu, 'Label','Swap String...', 'Callback', #swapBeginCallback);
set(h, 'uicontextmenu',hCMenu)
function swapBeginCallback(hObj,ev)
%# save the handle of the textbox we right clicked on
hLastBox = gco;
%# we must disable textboxes to be able to fire the ButtonDownFcn
set(h, 'ButtonDownFcn',#swapEndCallback)
set(h, 'Enable','off')
%# show instruction to user
if isFirstTime
isFirstTime = false;
msgbox('Now select textbox you want to switch string with');
end
end
function swapEndCallback(hObj,ev)
%# re-enable textboxes, and reset ButtonDownFcn handler
set(h, 'Enable','on')
set(h, 'ButtonDownFcn',[])
%# swap strings
str = get(gcbo,'String');
set(gcbo, 'String',get(hLastBox,'String'))
set(hLastBox, 'String',str)
end
end

Blackberry -- Updating screen changes drawing order of manager its field elements

Scenario
In a screen I have 2 managers: 1) menu manager at the top and 2) body manager that has info/button elements. The menu manager does custom drawing so that its menu elements (LabelFields) are properly spaced.
Core Issue - Manager and subfield drawing order
The screen draws fine except when the user preforms an action (clicks a button) that results in an element withing the body manager being added/removed. Once field elements are added/removed from the body, the order in which the menu is drawn gets mixed up.
When the body manager adds or removes a field, instead of the menu manager drawing itself and then its sub elements (label fields), the menu manager begins to draw its sub elements and then itself; thus painting on top of the label fields and making them look like they've disappeared.
Comments
Already tried invalidate and other options -- I've tried to call invalidate, invalidateall, updateDisplay... after adding/removing field elements from body. All without success.
Removing custom sublayout works -- The only way that I can resolve this issue is to remove the menu managers custom sublayout logic. Unfortunately the menu system then draws in a traditional manner and does not provide enough spacing.
Below is the sublayout code for the menu manager, am I missing something here?
public void sublayout(int iWidth, int iHeight)
{
final int iNumFields = getFieldCount();
int maxHeight = 0;
final int segmentWidth = iWidth / iNumFields;
final int segmentWidthHalf = segmentWidth / 2;
for (int i = 0; i < iNumFields; i++)
{
final Item currentField = (Item)this.getField(i);
// 1. Use index to compute bounds of the field
final int xSegmentTrueCenter = segmentWidth * i + segmentWidthHalf;
// 2. center field inbetween bounds using field width (find fill width of text)
final int xFieldStart = xSegmentTrueCenter - currentField.getFont().getAdvance(currentField.getText())/2;
// set up position
setPositionChild(currentField, xFieldStart, getContentTop() + MenuAbstract.PADDING_VERTICAL);
// allow child to draw itself
layoutChild(currentField, iWidth, currentField.getHeight());
// compute max height of the field
//int fieldheight = currentField.getHeight();
maxHeight = currentField.getHeight() > maxHeight
? currentField.getHeight() + 2 * MenuAbstract.PADDING_VERTICAL
: maxHeight;
}
this.setExtent(iWidth, maxHeight);
}
Final Questions
Ultimately I want to keep the custom layout of the menu manager while being allowed to redraw field elements. Here are my final questions:
Have you experienced this before?
Why would the menu manager begin drawing in the wrong order when a field element is added/remove to the screen?
Does the native Manager.sublayout() do something that I'm not to maintain drawing order?
I haven't seen the behavior you describe, but the following line is a little troubling:
// allow child to draw itself
layoutChild(currentField, iWidth, currentField.getHeight());
getHeight() shouldn't return a sensible value until the field has had setExtent called through the layoutChild method. Though I'd expect that it would cause problems in all cases - not sure why this would work the first time around. In your logic I think you can safely just use iHeight instead of currentField.getHeight() in that line. The field will only make itself as big as it needs to be - it won't use all of iHeight unless it's something like a VerticalFieldManager

Resources