Michael L Brereton - 02 January 2008, http://www.ewesoft.com/
<<
Previous: Handles And Tasks
>>
Next: Images and Pictures
Containers
such as Panel and CellPanel are not meant to be easily changed
after being displayed. Although this is possible, it can be quite complicated.
If you need to change a Control or set of Controls you should either use a SingleContainer
or use one of the containers that implement MultiPanel.
It is
possible to hide and reveal controls programmatically, while adjusting the size
of the containing Window appropriately. To hide a Control and its children call
hide(boolean update) on the Control. You can then call unhide(boolean
update) to show the Control again. For every call of hide() there must be a
matching call of unhide(). Two calls of hide() will require two calls of
unhide() to get the Control to reappear.
When a
Control is hidden or unhidden the relayout() method is invoked on a
parent of the Control if the update parameter is true (this should
usually be set true). The parent Container that is used defaults to the
containing Frame for the Control (determined by getFrame() at
runtime) but this can be changed to a
different parent using the method void setHiddenParent(boolean startHidden, Container
parent). This method indicates whether the Control should be initially
hidden (if startHidden is true) and which parent is to be used for
hiding the Control (if it is null it will default to getFrame()). If the hide
parent is not the Frame for the Control, then the containing Window will not be
resized to adjust to the new layout.
The example
below illustrates how hide() and unhide() work.
package evesamples.ui;
import eve.ui.*;
import eve.ui.event.*;
/**
* This class tests the HideControl class.
*/
//####################################################
public class DynamicPanel extends Form{
private Input searchFor, replaceWith;
private Button moreDetails, search;
private CellPanel details;
private boolean showingDetails;
private CheckBox matchCase, wholeWord, regularEx, wrapSearch;
private final String less = " Less Details ";
private final String more = " More Details ";
public DynamicPanel()
{
title = "Search and Replace";
InputStack is = new InputStack();
is.inputLength = 30;
searchFor = is.addInput("Search For:","Anything");
replaceWith = is.addInput("Replace With:","Nothing");
addLast(is).setCell(HSTRETCH);
//
details = is = new InputStack();
is.columns = 2;
matchCase = is.addCheckBox("Match Case");
wholeWord = is.addCheckBox("Whole Words");
regularEx = is.addCheckBox("Regular Expression");
wrapSearch = is.addCheckBox("Wrap Search");
is.setText("Search Options");
addLast(details).setCell(HSTRETCH);
//
// Set the details to be initially hidden.
//
details.setHiddenParent(true,null);
//
addButton(moreDetails = new Button(more));
moreDetails.modify(NoFocus,0);
showingDetails = false;
addButton(search = new Button("Search"));
//
doButtons(DEFCANCELB);
}
public void onControlEvent(ControlEvent ev)
{
if (ev.type == ControlEvent.PRESSED){
if (ev.target == moreDetails){
if (showingDetails){
moreDetails.setText(more);
details.hide(true);
}else{
moreDetails.setText(less);
details.unhide(true);
}
showingDetails = !showingDetails;
}
}
super.onControlEvent(ev);
}
}
//####################################################
This is how
the Form looks when created. The details.setHiddenParent(true,null);
line tells the Form that the details control should initially be hidden, and
that the parent for unhiding the control should be the full Frame of the Form
at runtime (because the parent parameter was null).
After pressing
the “More Details” button the Form is updated and the Window is resized to look
like this:
This is a
container that you add a single control to but which will allow that control to
be changed dynamically on-screen. You add the first control and change the
displayed control using the setControl() methods. That single control
can, of course itself be a container, and so you can effectively add and remove
any number of controls dynamically by placing them all in a Panel which you
then place in a SingleContainer.
The example
below shows how to use a SingleContainer using an Editor as the base
Form. The Editor class will be explained in a later chapter.
package evesamples.ui;
import eve.fx.Insets;
import eve.sys.Locale;
import eve.ui.*;
import eve.ui.data.Editor;
import eve.util.mVector;
public class TestSingleContainer extends Editor{
Panel one, two, three;
SingleContainer single;
// ===================================================================
public TestSingleContainer()
// ===================================================================
{
title = "Testing Single Container";
Panel p = new Panel();
p.defaultTags.set(Panel.TAG_INSETS,new Insets(2,2,0,0));
p.setText("Testing the panel");
Label l;
p.addNext(l = new MessageArea("Hello\nGood to meet you."));
l.alignment = l.anchor = RIGHT;
p.addLast(new Button("There!"));
p.addNext(l = new MessageArea("How\nNice to see you,\nI trust you are well"));
l.alignment = CENTER; l.anchor = LEFT;
p.addLast(new Button("are you doing?")).setTag(TAG_INSETS,new Insets(4,4,4,4));
p.addLast(new Button("I'm alone"));
one = p;
single = new SingleContainer();
single.setControl(one);
addLast(single);
addNext(addField(new Button("One"),"uno")).setCell(HSTRETCH);
addNext(addField(new Button("Two"),"dos")).setCell(HSTRETCH);
addNext(addField(new Button("Three"),"tres")).setCell(HSTRETCH);
two = new CellPanel();
p = two;
p.addLast(new Button("are you doing?")).setTag(TAG_INSETS,new Insets(4,4,4,4));
p.addLast(new Button("I'm alone"));
three = getLocaleList();
}
// ===================================================================
public void action(String name,Editor ed)
// ===================================================================
{
if (name.equals("uno")) {
ed.getWindow().setTitle("First set!");
single.setControl(one,true);
}
if (name.equals("dos")) {
ed.getWindow().setTitle("Second set!");
single.setControl(two,true);
}
if (name.equals("tres")) {
ed.getWindow().setTitle("Third set!");
single.setControl(three,true);
}
}
// -------------------------------------------------------------------
static Panel getLocaleList()
// -------------------------------------------------------------------
{
int [] ids = Locale.getAllIDs(0);
String [] locales = new String[ids.length];
Locale locale = new Locale();
for (int i = 0; i<ids.length; i++){
locale.set(ids[i]);
locales[i] = locale.toString();
}
List list = new List(10,40,false);
mVector.addAll(list.items,locales);
return new ScrollBarPanel(list);
}
}
Containers
which implement this interface allow you to change the control it displays
between a set of controls that you add via addItem(Control c, String
tabName, String longName). The tabName specifies the on-screen
display name for that control. For a tabbed display, this will be displayed in
the tab. The longName is an optional name (it may be null) for display
in special circumstances and gives a more detailed description of the control
being added.
The Control
being added may itself be placed in another container before being added as an
item to the MultiPanel – this is completely up to the implementing MultiPanel.
The various select() methods are used to switch between the added
controls.
This is an
extension of the MultiPanel interface and it can only be implemented by controls
that use a CardPanel as the underlying dynamic control display. It allows for
the specifying of more advanced data (such as icons for individual items) and
for providing access to the underlying CardPanel.
There are
two MultiCardPanel implementations provided: a CardPanel and a TabbedPanel.
This is a
MultiCardPanel that can only have its displayed control changed
programmatically via the select() methods. That is, the CardPanel
provides no user controls to switch between the added controls.
The
CardPanel is usually used as the main implementation of a MultiPanel – the only
extra controls needed is a control or set of controls to allow the user to
switch between the available items.
The
CardPanel, by default, will place all added controls in a ScrollBarPanel,
thereby ensuring that its contents will always be fully accessible. However if
you do not wish this to happen you can set the autoScroll field to be false.
This is a
MultiCardPanel that actually uses a CardPanel for its implementation. In fact
you can access its contained CardPanel through the cardPanel field (you
would need to do this if you want to switch off the autoScroll feature).
It then uses a set of tabs as the user method for switching between the various
added controls.
The Eve
TabbedPanel actually provides significant functionality and flexibility. An
entire Chapter on the TabbedPanel class will be done for the advanced UI
programming tutorial.