This commit is contained in:
Shyotl
2014-08-22 03:55:21 -05:00
9 changed files with 147 additions and 95 deletions

View File

@@ -46,16 +46,36 @@
static LLRegisterWidget<LLRadioGroup> r("radio_group"); static LLRegisterWidget<LLRadioGroup> r("radio_group");
/*
* A checkbox control with use_radio_style == true.
*/
class LLRadioCtrl : public LLCheckBoxCtrl
{
public:
LLRadioCtrl(const std::string& name, const LLRect& rect, const std::string& label, const std::string& value = "", const LLFontGL* font = NULL, commit_callback_t commit_callback = NULL);
/*virtual*/ ~LLRadioCtrl();
virtual LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void setValue(const LLSD& value);
LLSD getPayload() { return mPayload; }
protected:
friend class LLUICtrlFactory;
LLSD mPayload; // stores data that this item represents in the radio group
};
LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect, LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect,
S32 initial_index, commit_callback_t commit_callback, S32 initial_index, commit_callback_t commit_callback,
BOOL border) : bool border, bool allow_deselect) :
LLUICtrl(name, rect, TRUE, commit_callback, FOLLOWS_LEFT | FOLLOWS_TOP), LLUICtrl(name, rect, TRUE, commit_callback, FOLLOWS_LEFT | FOLLOWS_TOP),
mSelectedIndex(initial_index) mSelectedIndex(initial_index),
mAllowDeselect(allow_deselect)
{ {
init(border); init(border);
} }
void LLRadioGroup::init(BOOL border) void LLRadioGroup::init(bool border)
{ {
if (border) if (border)
{ {
@@ -67,12 +87,19 @@ void LLRadioGroup::init(BOOL border)
} }
LLRadioGroup::~LLRadioGroup() LLRadioGroup::~LLRadioGroup()
{ {
} }
// virtual
BOOL LLRadioGroup::postBuild()
{
if (!mRadioButtons.empty())
{
mRadioButtons[0]->setTabStop(true);
}
return TRUE;
}
// virtual // virtual
void LLRadioGroup::setEnabled(BOOL enabled) void LLRadioGroup::setEnabled(BOOL enabled)
@@ -133,16 +160,39 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event) BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event)
{ {
if (index < 0 || index >= (S32)mRadioButtons.size()) if ((S32)mRadioButtons.size() <= index )
{ {
return FALSE; return FALSE;
} }
if (mSelectedIndex >= 0)
{
LLRadioCtrl* old_radio_item = mRadioButtons[mSelectedIndex];
old_radio_item->setTabStop(false);
old_radio_item->setValue( FALSE );
}
else
{
mRadioButtons[0]->setTabStop(false);
}
mSelectedIndex = index; mSelectedIndex = index;
if (mSelectedIndex >= 0)
{
LLRadioCtrl* radio_item = mRadioButtons[mSelectedIndex];
radio_item->setTabStop(true);
radio_item->setValue( TRUE );
if (hasFocus())
{
radio_item->focusFirstItem(FALSE, FALSE);
}
}
if (!from_event) if (!from_event)
{ {
setControlValue(getSelectedIndex()); setControlValue(getValue());
} }
return TRUE; return TRUE;
@@ -207,41 +257,23 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask)
return handled; return handled;
} }
void LLRadioGroup::draw() BOOL LLRadioGroup::handleMouseDown(S32 x, S32 y, MASK mask)
{ {
S32 current_button = 0; // grab focus preemptively, before child button takes mousecapture
//
BOOL take_focus = FALSE; if (hasTabStop())
if (gFocusMgr.childHasKeyboardFocus(this))
{ {
take_focus = TRUE; focusFirstItem(FALSE, FALSE);
} }
for (button_list_t::iterator iter = mRadioButtons.begin(); return LLUICtrl::handleMouseDown(x, y, mask);
iter != mRadioButtons.end(); ++iter)
{
LLRadioCtrl* radio = *iter;
BOOL selected = (current_button == mSelectedIndex);
radio->setValue( selected );
if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radio))
{
// don't flash keyboard focus when navigating via keyboard
BOOL DONT_FLASH = FALSE;
radio->focusFirstItem(FALSE, DONT_FLASH);
}
current_button++;
}
LLView::draw();
} }
// When adding a button, we need to ensure that the radio // When adding a button, we need to ensure that the radio
// group gets a message when the button is clicked. // group gets a message when the button is clicked.
LLRadioCtrl* LLRadioGroup::addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font ) LLRadioCtrl* LLRadioGroup::addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font, const std::string& payload)
{ {
// Highlight will get fixed in draw method above LLRadioCtrl* radio = new LLRadioCtrl(name, rect, label, payload, font, boost::bind(&LLRadioGroup::onClickButton, this, _1));
LLRadioCtrl* radio = new LLRadioCtrl(name, rect, label, font, boost::bind(&LLRadioGroup::onClickButton, this, _1));
addChild(radio); addChild(radio);
mRadioButtons.push_back(radio); mRadioButtons.push_back(radio);
return radio; return radio;
@@ -252,7 +284,7 @@ LLRadioCtrl* LLRadioGroup::addRadioButton(const std::string& name, const std::st
void LLRadioGroup::onClickButton(LLUICtrl* ctrl) void LLRadioGroup::onClickButton(LLUICtrl* ctrl)
{ {
// llinfos << "LLRadioGroup::onClickButton" << llendl; // LL_INFOS() << "LLRadioGroup::onClickButton" << LL_ENDL;
LLRadioCtrl* clicked_radio = dynamic_cast<LLRadioCtrl*>(ctrl); LLRadioCtrl* clicked_radio = dynamic_cast<LLRadioCtrl*>(ctrl);
if (!clicked_radio) if (!clicked_radio)
return; return;
@@ -263,9 +295,15 @@ void LLRadioGroup::onClickButton(LLUICtrl* ctrl)
LLRadioCtrl* radio = *iter; LLRadioCtrl* radio = *iter;
if (radio == clicked_radio) if (radio == clicked_radio)
{ {
// llinfos << "clicked button " << counter << llendl; if (index == mSelectedIndex && mAllowDeselect)
setSelectedIndex(index); {
setControlValue(index); // don't select anything
setSelectedIndex(-1);
}
else
{
setSelectedIndex(index);
}
// BUG: Calls click callback even if button didn't actually change // BUG: Calls click callback even if button didn't actually change
onCommit(); onCommit();
@@ -281,13 +319,12 @@ void LLRadioGroup::onClickButton(LLUICtrl* ctrl)
void LLRadioGroup::setValue( const LLSD& value ) void LLRadioGroup::setValue( const LLSD& value )
{ {
std::string value_name = value.asString();
int idx = 0; int idx = 0;
for (button_list_t::const_iterator iter = mRadioButtons.begin(); for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter) iter != mRadioButtons.end(); ++iter)
{ {
LLRadioCtrl* radio = *iter; LLRadioCtrl* radio = *iter;
if (radio->getName() == value_name) if (radio->getPayload().asString() == value.asString())
{ {
setSelectedIndex(idx); setSelectedIndex(idx);
idx = -1; idx = -1;
@@ -304,8 +341,7 @@ void LLRadioGroup::setValue( const LLSD& value )
} }
else else
{ {
llwarns << "LLRadioGroup::setValue: radio_item with name=\"" << value_name << "\" not found, radio_group values are set by radio_item name not value. Falling back on LLUICtrl::setValue." << llendl; setSelectedIndex(-1, TRUE);
LLUICtrl::setValue(value);
} }
} }
} }
@@ -317,7 +353,7 @@ LLSD LLRadioGroup::getValue() const
for (button_list_t::const_iterator iter = mRadioButtons.begin(); for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter) iter != mRadioButtons.end(); ++iter)
{ {
if (idx == index) return LLSD((*iter)->getName()); if (idx == index) return LLSD((*iter)->getPayload());
++idx; ++idx;
} }
return LLSD(); return LLSD();
@@ -333,6 +369,7 @@ LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
// Attributes // Attributes
node->createChild("draw_border", TRUE)->setBoolValue(mHasBorder); node->createChild("draw_border", TRUE)->setBoolValue(mHasBorder);
node->createChild("allow_deselect", TRUE)->setBoolValue(mAllowDeselect);
// Contents // Contents
@@ -355,17 +392,21 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
U32 initial_value = 0; U32 initial_value = 0;
node->getAttributeU32("initial_value", initial_value); node->getAttributeU32("initial_value", initial_value);
BOOL draw_border = TRUE; bool draw_border = true;
node->getAttributeBOOL("draw_border", draw_border); node->getAttribute_bool("draw_border", draw_border);
bool allow_deselect = false;
node->getAttribute_bool("allow_deselect", allow_deselect);
LLRect rect; LLRect rect;
createRect(node, rect, parent, LLRect()); createRect(node, rect, parent, LLRect());
LLRadioGroup* radio_group = new LLRadioGroup("radio_group", LLRadioGroup* radio_group = new LLRadioGroup("radio_group",
rect, rect,
initial_value, initial_value,
NULL, NULL,
draw_border); draw_border,
allow_deselect);
const std::string& contents = node->getValue(); const std::string& contents = node->getValue();
@@ -406,7 +447,13 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
createRect(child, item_rect, radio_group, rect); createRect(child, item_rect, radio_group, rect);
std::string item_label = child->getTextContents(); std::string item_label = child->getTextContents();
LLRadioCtrl* radio = radio_group->addRadioButton("radio", item_label, item_rect, font); node->getAttributeString("label", item_label);
std::string item_name("radio");
node->getAttributeString("name", item_name);
std::string payload(item_name); // Support old-style name as payload
node->getAttributeString("value", payload);
node->getAttributeString("initial_value", payload); // Synonym
LLRadioCtrl* radio = radio_group->addRadioButton(item_name, item_label, item_rect, font, payload);
radio->initFromXML(child, radio_group); radio->initFromXML(child, radio_group);
} }
@@ -432,11 +479,10 @@ LLUUID LLRadioGroup::getCurrentID() const
BOOL LLRadioGroup::setSelectedByValue(const LLSD& value, BOOL selected) BOOL LLRadioGroup::setSelectedByValue(const LLSD& value, BOOL selected)
{ {
S32 idx = 0; S32 idx = 0;
std::string value_string = value.asString();
for (button_list_t::const_iterator iter = mRadioButtons.begin(); for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter) iter != mRadioButtons.end(); ++iter)
{ {
if((*iter)->getName() == value_string) if((*iter)->getPayload().asString() == value.asString())
{ {
setSelectedIndex(idx); setSelectedIndex(idx);
return TRUE; return TRUE;
@@ -455,11 +501,10 @@ LLSD LLRadioGroup::getSelectedValue()
BOOL LLRadioGroup::isSelected(const LLSD& value) const BOOL LLRadioGroup::isSelected(const LLSD& value) const
{ {
S32 idx = 0; S32 idx = 0;
std::string value_string = value.asString();
for (button_list_t::const_iterator iter = mRadioButtons.begin(); for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter) iter != mRadioButtons.end(); ++iter)
{ {
if((*iter)->getName() == value_string) if((*iter)->getPayload().asString() == value.asString())
{ {
if (idx == mSelectedIndex) if (idx == mSelectedIndex)
{ {
@@ -481,6 +526,17 @@ BOOL LLRadioGroup::operateOnAll(EOperation op)
return FALSE; return FALSE;
} }
LLRadioCtrl::LLRadioCtrl(const std::string& name, const LLRect& rect, const std::string& label, const std::string& value, const LLFontGL* font, commit_callback_t commit_callback)
: LLCheckBoxCtrl(name, rect, label, font, commit_callback, FALSE, RADIO_STYLE),
mPayload(value)
{
setTabStop(FALSE);
// use name as default "Value" for backwards compatibility
if (value.empty())
{
mPayload = name;
}
}
LLRadioCtrl::~LLRadioCtrl() LLRadioCtrl::~LLRadioCtrl()
{ {
@@ -499,7 +555,7 @@ LLXMLNodePtr LLRadioCtrl::getXML(bool save_children) const
node->setName(LL_RADIO_ITEM_TAG); node->setName(LL_RADIO_ITEM_TAG);
node->setStringValue(getLabel()); node->createChild("value", TRUE)->setStringValue(mPayload);
return node; return node;
} }

View File

@@ -37,26 +37,6 @@
#include "llcheckboxctrl.h" #include "llcheckboxctrl.h"
#include "llctrlselectioninterface.h" #include "llctrlselectioninterface.h"
/*
* A checkbox control with use_radio_style == true.
*/
class LLRadioCtrl : public LLCheckBoxCtrl
{
public:
LLRadioCtrl(const std::string& name, const LLRect& rect, const std::string& label, const LLFontGL* font = NULL,
commit_callback_t commit_callback = NULL) :
LLCheckBoxCtrl(name, rect, label, font, commit_callback, FALSE, RADIO_STYLE)
{
setTabStop(FALSE);
}
/*virtual*/ ~LLRadioCtrl();
virtual LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void setValue(const LLSD& value);
};
/* /*
* An invisible view containing multiple mutually exclusive toggling * An invisible view containing multiple mutually exclusive toggling
* buttons (usually radio buttons). Automatically handles the mutex * buttons (usually radio buttons). Automatically handles the mutex
@@ -66,25 +46,32 @@ class LLRadioGroup
: public LLUICtrl, public LLCtrlSelectionInterface : public LLUICtrl, public LLCtrlSelectionInterface
{ {
public: public:
// Radio group constructor. Doesn't rely on
// needing a control // Radio group constructor. Doesn't rely on needing a control
LLRadioGroup(const std::string& name, const LLRect& rect, LLRadioGroup(const std::string& name, const LLRect& rect,
S32 initial_index, S32 initial_index,
commit_callback_t commit_callback, commit_callback_t commit_callback,
BOOL border = TRUE); bool border = true, bool allow_deselect = false);
protected:
friend class LLUICtrlFactory;
public:
virtual ~LLRadioGroup(); virtual ~LLRadioGroup();
virtual BOOL postBuild();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual void setEnabled(BOOL enabled); virtual void setEnabled(BOOL enabled);
virtual LLXMLNodePtr getXML(bool save_children = true) const; virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void setIndexEnabled(S32 index, BOOL enabled); void setIndexEnabled(S32 index, BOOL enabled);
// return the index value of the selected item // return the index value of the selected item
S32 getSelectedIndex() const { return mSelectedIndex; } S32 getSelectedIndex() const { return mSelectedIndex; }
// set the index value programatically // set the index value programatically
BOOL setSelectedIndex(S32 index, BOOL from_event = FALSE); BOOL setSelectedIndex(S32 index, BOOL from_event = FALSE);
@@ -92,14 +79,10 @@ public:
virtual void setValue(const LLSD& value ); virtual void setValue(const LLSD& value );
virtual LLSD getValue() const; virtual LLSD getValue() const;
// Draw the group, but also fix the highlighting based on the control.
void draw();
// You must use this method to add buttons to a radio group. // You must use this method to add buttons to a radio group.
// Don't use addChild -- it won't set the callback function // Don't use addChild -- it won't set the callback function
// correctly. // correctly.
LLRadioCtrl* addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font); class LLRadioCtrl* addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font, const std::string& payload = "");
LLRadioCtrl* getRadioButton(const S32& index) { return mRadioButtons[index]; }
// Update the control as needed. Userdata must be a pointer to the button. // Update the control as needed. Userdata must be a pointer to the button.
void onClickButton(LLUICtrl* clicked_radio); void onClickButton(LLUICtrl* clicked_radio);
@@ -123,14 +106,15 @@ public:
private: private:
// protected function shared by the two constructors. // protected function shared by the two constructors.
void init(BOOL border); void init(bool border);
S32 mSelectedIndex; S32 mSelectedIndex;
typedef std::vector<LLRadioCtrl*> button_list_t;
typedef std::vector<class LLRadioCtrl*> button_list_t;
button_list_t mRadioButtons; button_list_t mRadioButtons;
BOOL mHasBorder; bool mHasBorder;
bool mAllowDeselect; // user can click on an already selected option to deselect it
}; };
#endif #endif

View File

@@ -1787,7 +1787,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
child_list_t::const_iterator it, end=childs->end(); child_list_t::const_iterator it, end=childs->end();
for (it=childs->begin(); it!=end; ++it) for (it=childs->begin(); it!=end; ++it)
{ {
LLRadioCtrl *ctrl = dynamic_cast<LLRadioCtrl*>(*it); LLView* ctrl = *it;
if (ctrl && (ctrl->getName() == "texture")) if (ctrl && (ctrl->getName() == "texture"))
{ {
ctrl->setLabelArg("[UPLOADFEE]", fee); ctrl->setLabelArg("[UPLOADFEE]", fee);

View File

@@ -81,8 +81,6 @@ private:
LLIconCtrl* mIcon; LLIconCtrl* mIcon;
LLLineEditor* mLineEditor; LLLineEditor* mLineEditor;
LLRadioGroup* mRadioGroup; LLRadioGroup* mRadioGroup;
LLRadioCtrl* mRadio1;
LLRadioCtrl* mRadio2;
LLScrollContainer* mScroll; LLScrollContainer* mScroll;
LLScrollListCtrl* mScrollList; LLScrollListCtrl* mScrollList;
LLTabContainer* mTab; LLTabContainer* mTab;

View File

@@ -2851,6 +2851,14 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
restoreItem(); restoreItem();
return; return;
} }
// <singu> Move displaced inventory to lost and found
else if ("move_to_lost_and_found" == action)
{
gInventory.changeCategoryParent(getCategory(), gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND), TRUE);
gInventory.addChangedMask(LLInventoryObserver::REBUILD, mUUID);
gInventory.notifyObservers();
}
// </singu>
#ifdef DELETE_SYSTEM_FOLDERS #ifdef DELETE_SYSTEM_FOLDERS
else if ("delete_system_folder" == action) else if ("delete_system_folder" == action)
{ {
@@ -3365,6 +3373,14 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
mWearables=TRUE; mWearables=TRUE;
} }
} }
// <singu> Move displaced inventory to lost and found
else if (!isAgentInventory())
{
const LLUUID& library(gInventory.getLibraryRootFolderID());
if (library == mUUID || gInventory.isObjectDescendentOf(mUUID, library))
mItems.push_back(std::string("Move to Lost And Found"));
}
// </singu>
// Preemptively disable system folder removal if more than one item selected. // Preemptively disable system folder removal if more than one item selected.
if ((flags & FIRST_SELECTED_ITEM) == 0) if ((flags & FIRST_SELECTED_ITEM) == 0)

View File

@@ -13,8 +13,6 @@
<!-- Default Args - these arguments will be replaced in all strings --> <!-- Default Args - these arguments will be replaced in all strings -->
<string name="SECOND_LIFE">Second Life</string> <string name="SECOND_LIFE">Second Life</string>
<string name="APP_NAME">Singularity Viewer</string>
<string name="CAPITALIZED_APP_NAME">SINGULARITY VIEWER</string>
<string name="SECOND_LIFE_GRID">Second Life-Grid:</string> <string name="SECOND_LIFE_GRID">Second Life-Grid:</string>
<string name="SUPPORT_SITE">Second Life Support-Portal</string> <string name="SUPPORT_SITE">Second Life Support-Portal</string>

View File

@@ -227,6 +227,9 @@
name="Delete" width="128"> name="Delete" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="delete" /> <on_click filter="" function="Inventory.DoToSelected" userdata="delete" />
</menu_item_call> </menu_item_call>
<menu_item_call label="Move to Lost And Found" mouse_opaque="true" name="Move to Lost And Found">
<on_click function="Inventory.DoToSelected" userdata="move_to_lost_and_found" />
</menu_item_call>
<menu_item_call label="Delete System Folder" mouse_opaque="true" name="Delete System Folder"> <menu_item_call label="Delete System Folder" mouse_opaque="true" name="Delete System Folder">
<on_click function="Inventory.DoToSelected" userdata="delete_system_folder" /> <on_click function="Inventory.DoToSelected" userdata="delete_system_folder" />
</menu_item_call> </menu_item_call>

View File

@@ -998,7 +998,7 @@
<on_click function="PromptShowURL" name="RequestFeature_url" userdata="WebLaunchSinguIssue,http://code.google.com/p/singularity-viewer/issues/entry?template=Feature%20request"/> <on_click function="PromptShowURL" name="RequestFeature_url" userdata="WebLaunchSinguIssue,http://code.google.com/p/singularity-viewer/issues/entry?template=Feature%20request"/>
</menu_item_call> </menu_item_call>
</menu> </menu>
<menu_item_call bottom="-313" enabled="true" height="19" label="About [APP_NAME]..." left="0" <menu_item_call bottom="-313" enabled="true" height="19" label="About [SHORT_APP_NAME]..." left="0"
mouse_opaque="true" name="About Second Life..." width="166"> mouse_opaque="true" name="About Second Life..." width="166">
<on_click function="ShowFloater" userdata="about" /> <on_click function="ShowFloater" userdata="about" />
</menu_item_call> </menu_item_call>

View File

@@ -21,9 +21,6 @@ Asegurate que has ingresado el URI de inicio de sesión correcto. Un ejemplo de
<!-- Default Args - these arguments will be replaced in all strings --> <!-- Default Args - these arguments will be replaced in all strings -->
<string name="SECOND_LIFE">Second Life</string> <string name="SECOND_LIFE">Second Life</string>
<string name="APP_NAME">Singularity Viewer</string>
<string name="CAPITALIZED_APP_NAME">SINGULARITY VIEWER</string>
<string name="SHORT_APP_NAME">Singularity</string>
<string name="SECOND_LIFE_GRID">Grid Second Life</string> <string name="SECOND_LIFE_GRID">Grid Second Life</string>
<string name="SUPPORT_SITE">Portal de Soporte de Second Life</string> <string name="SUPPORT_SITE">Portal de Soporte de Second Life</string>