Adding a dialog: Difference between revisions
James Linden (talk | contribs) No edit summary |
James Linden (talk | contribs) No edit summary |
||
| Line 1: | Line 1: | ||
{{OSWikiLearnBox|parent=Viewer architecture}} | |||
Windows and dialogs in Second Life are implemented as LLFloater objects. The class hierarchy is: | Windows and dialogs in Second Life are implemented as LLFloater objects. The class hierarchy is: | ||
| Line 17: | Line 18: | ||
A basic floater header looks like this: | A basic floater header looks like this: | ||
<pre> | |||
#include "llfloater.h" | |||
class LLFloaterFoo : public LLFloater | |||
{ | |||
public: | |||
LLFloaterFoo(); | |||
// by convention, this shows the floater and does instance management | |||
static void show(void*); | |||
private: | |||
// when a line editor loses keyboard focus, it is committed. | |||
// commit callbacks are named onCommitWidgetName by convention. | |||
void onCommitBaz(LLUICtrl* ctrl, void *userdata); | |||
// by convention, button callbacks are named onClickButtonLabel | |||
void onClickHippo(void* userdata); | |||
// no pointers to widgets here - they are referenced by name | |||
}; | |||
The XML data definition should look like this: | The XML data definition should look like this: | ||
| Line 80: | Line 81: | ||
</text> | </text> | ||
<!-- | |||
Line editor names end in _edit by convention. | |||
mouse_opaque means it blocks mouse clicks, rather than passing on to underlying view | |||
max_length is in bytes, not Unicode characters | |||
--> | |||
<line_editor | |||
name="baz_edit" | |||
width="120" | |||
height="20" | |||
left="10" | |||
bottom_delta="-30" | |||
follows="left|bottom" | |||
hidden="false" | |||
mouse_opaque="true" | |||
max_length="31" | |||
font="SansSerif" | |||
bevel_style="in" | |||
border_style="line" | |||
border_thickness="1" | |||
select_all_on_focus_received="true" | |||
/> | |||
<!-- | <!-- | ||
| Line 96: | Line 119: | ||
width="100" | width="100" | ||
height="20" | height="20" | ||
follows=" | follows="bottom|left" | ||
/> | /> | ||
</floater> | </floater> | ||
</pre> | </pre> | ||
The C++ code for this floater looks like: | |||
<pre> | |||
#include "llviewerprecompiledheaders.h" // must be first include | |||
#include "llfloaterfoo.h" | |||
#include "llvieweruictrlfactory.h" // builds floaters from XML | |||
LLFloaterFoo::LLFloaterFoo() | |||
: LLFloater("floater_foo") | |||
{ | |||
gUICtrlFactory->buildFloater(this, "floater_foo.xml"); | |||
childSetCommitCallback("baz_edit", onCommitBaz, this); | |||
childSetAction("hippo_btn", onClickHippo, this); | |||
setDefaultBtn("hippo_btn"); | |||
} | |||
// static | |||
void LLFloaterFoo::show(void*) | |||
{ | |||
LLFloaterFoo* self = new LLFloaterFoo(); | |||
self->open(); | |||
} | |||
// static | |||
void LLFloaterFoo::onCommitBaz(LLUICtrl* ctrl, void* userdata) | |||
{ | |||
LLFloaterFoo* self = (LLFloaterFoo*)userdata; | |||
LLString text = self->childGetText("baz_edit"); | |||
llinfos << "baz contains: " << text << llendl; | |||
} | |||
// static | |||
void LLFloaterFoo::onClickHippo(void* userdata) | |||
{ | |||
LLFloaterFoo* self = (LLFloaterFoo*)userdata; | |||
llinfos << "Hippo! from " << self->getName() << llendl; | |||
} | |||
</pre> | |||
Finally, to test out this floater you'll need to add a menu item that calls the show() method. See [Adding a menu item]. | |||
Revision as of 12:09, 3 November 2006
Windows and dialogs in Second Life are implemented as LLFloater objects. The class hierarchy is:
LLFloaterFoo - a "foo" dialog LLFloater - generic window or dialog with close box, minimize box, etc. LLPanel - rectangular area with dark background, has functions like childSetText(), childGetValue() LLUICtrl - any widget that can take keyboard focus LLView - base class, container for UI widget children
Create a new C++ header and source file to hold your new class. By convention these are called llfloaterfoo.h and .cpp. Place them in the newview directory.
You'll also need a new XML description file. These are found in the indra/newview/skins/xui/en-us directory. It's easiest to copy an existing file and modify it. Name the new file floater_foo.xml.
Important - Second Life UI uses OpenGL coordinates, so 0,0 is at the bottom left corner.
Let's make a floater that has a text label "bar", a text line input field "baz", and a button "hippo".
A basic floater header looks like this:
#include "llfloater.h"
class LLFloaterFoo : public LLFloater
{
public:
LLFloaterFoo();
// by convention, this shows the floater and does instance management
static void show(void*);
private:
// when a line editor loses keyboard focus, it is committed.
// commit callbacks are named onCommitWidgetName by convention.
void onCommitBaz(LLUICtrl* ctrl, void *userdata);
// by convention, button callbacks are named onClickButtonLabel
void onClickHippo(void* userdata);
// no pointers to widgets here - they are referenced by name
};
The XML data definition should look like this:
<pre>
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
<!-- Floaters can optionally have their titlebar drag handle on the left.
If so, the title is not visible.
When a floater is resizable, a min_width and min_height must be specified. -->
<floater
name="foo_floater"
title="Foo"
can_resize="true"
can_minimize="true"
can_close="true"
can_drag_on_left="false"
width="275"
height="250"
min_width="80"
min_height="220"
>
<!--
By convention text fields are suffixed with _text.
Common fonts include SansSerif and SansSerifSmall. See LLFontGL::fontFromName for more.
Positions may be in absolute coordinates or as deltas.
bottom_delta = -40 indicates 40 pixels from the top edge.
follows indicates how the widget should move when the container is resized.
-->
<text name="bar_text"
font="SansSerifSmall"
left="10"
bottom_delta="-40"
width="260"
height="16"
follows="left|top"
>
bar is a generic programming identifier
</text>
<!--
Line editor names end in _edit by convention.
mouse_opaque means it blocks mouse clicks, rather than passing on to underlying view
max_length is in bytes, not Unicode characters
-->
<line_editor
name="baz_edit"
width="120"
height="20"
left="10"
bottom_delta="-30"
follows="left|bottom"
hidden="false"
mouse_opaque="true"
max_length="31"
font="SansSerif"
bevel_style="in"
border_style="line"
border_thickness="1"
select_all_on_focus_received="true"
/>
<!--
Buttons are suffixed with _btn by convention.
Note there is no association with a callback function here - it must be connected
in the C++ code.
bottom_delta here means from the TOP of the last widget, not the bottom.
-->
<button
name="hippo_btn"
label="Hippo"
font="SansSerifSmall"
left="10"
bottom_delta="-25"
width="100"
height="20"
follows="bottom|left"
/>
</floater>
The C++ code for this floater looks like:
#include "llviewerprecompiledheaders.h" // must be first include
#include "llfloaterfoo.h"
#include "llvieweruictrlfactory.h" // builds floaters from XML
LLFloaterFoo::LLFloaterFoo()
: LLFloater("floater_foo")
{
gUICtrlFactory->buildFloater(this, "floater_foo.xml");
childSetCommitCallback("baz_edit", onCommitBaz, this);
childSetAction("hippo_btn", onClickHippo, this);
setDefaultBtn("hippo_btn");
}
// static
void LLFloaterFoo::show(void*)
{
LLFloaterFoo* self = new LLFloaterFoo();
self->open();
}
// static
void LLFloaterFoo::onCommitBaz(LLUICtrl* ctrl, void* userdata)
{
LLFloaterFoo* self = (LLFloaterFoo*)userdata;
LLString text = self->childGetText("baz_edit");
llinfos << "baz contains: " << text << llendl;
}
// static
void LLFloaterFoo::onClickHippo(void* userdata)
{
LLFloaterFoo* self = (LLFloaterFoo*)userdata;
llinfos << "Hippo! from " << self->getName() << llendl;
}
Finally, to test out this floater you'll need to add a menu item that calls the show() method. See [Adding a menu item].