summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2013-01-23 17:47:08 -0800
committerMerov Linden <merov@lindenlab.com>2013-01-23 17:47:08 -0800
commita0112d6d78b17c5771b7b151d2fb9340bece3137 (patch)
tree7c8f68933cc1c0b09af188b99cd391a3f540c320
parent46a74c4e01e19c07b5ee966ebe9882c4209dc89c (diff)
parent0911dafd81b8360235eb6f6b85fac7153a5d4a02 (diff)
Pull merge with lindenlab/viewer-chui
-rw-r--r--indra/llui/llfolderview.cpp6
-rw-r--r--indra/llui/llfolderview.h3
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.cpp22
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.h6
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp8
-rw-r--r--indra/newview/llfloaterimcontainer.cpp19
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp32
-rw-r--r--indra/newview/llfloaterimsessiontab.h5
-rw-r--r--indra/newview/llimview.cpp2
-rw-r--r--indra/newview/llinventoryfunctions.cpp27
-rw-r--r--indra/newview/llinventoryfunctions.h1
-rwxr-xr-xindra/newview/llviewerwindow.cpp18
-rw-r--r--indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml19
-rw-r--r--indra/newview/skins/default/xui/en/menu_participant_view.xml20
14 files changed, 111 insertions, 77 deletions
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 324142f6c3..7c1ca017d7 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -399,6 +399,10 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void )
return NULL;
}
+LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void )
+{
+ return mSelectedItems;
+}
// Record the selected item and pass it down the hierachy.
BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,
@@ -752,8 +756,8 @@ void LLFolderView::removeSelectedItems()
{
// change selection on successful delete
setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus());
- }
}
+ }
arrangeAll();
}
else if (count > 1)
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index a6e0a3b4c0..05b2abb9d3 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -101,6 +101,7 @@ public:
};
friend class LLFolderViewScrollContainer;
+ typedef std::deque<LLFolderViewItem*> selected_items_t;
LLFolderView(const Params&);
virtual ~LLFolderView( void );
@@ -138,6 +139,7 @@ public:
// Get the last selected item
virtual LLFolderViewItem* getCurSelectedItem( void );
+ selected_items_t& getSelectedItems( void );
// Record the selected item and pass it down the hierarchy.
virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
@@ -261,7 +263,6 @@ protected:
protected:
LLHandle<LLView> mPopupMenuHandle;
- typedef std::deque<LLFolderViewItem*> selected_items_t;
selected_items_t mSelectedItems;
BOOL mKeyboardSelection;
BOOL mAllowMultiSelect;
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 824ff67972..15c42e8285 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -43,7 +43,8 @@
#include "lluuid.h"
static const F32 DND_TIMER = 3.0;
-const std::string toastName = "IMToast";
+const char * LLDoNotDisturbNotificationStorage::toastName = "IMToast";
+const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem";
LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER)
{
@@ -72,6 +73,8 @@ LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"))
, mDirty(false)
{
+ nameToPayloadParameterMap[toastName] = "SESSION_ID";
+ nameToPayloadParameterMap[offerName] = "object_id";
}
LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()
@@ -234,15 +237,16 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan
return channelPtr;
}
-void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id)
+void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, const LLUUID& id)
{
LLNotifications& instance = LLNotifications::instance();
LLNotificationChannelPtr channelPtr = getCommunicationChannel();
LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
LLNotificationPtr notification;
- LLSD substitutions;
- LLUUID notificationSessionID;
+ LLSD payload;
+ LLUUID notificationObjectID;
std::string notificationName;
+ std::string payloadVariable = nameToPayloadParameterMap[name];
LLCommunicationChannel::history_list_t::iterator it;
std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove;
@@ -252,18 +256,18 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi
++it)
{
notification = it->second;
- substitutions = notification->getSubstitutions();
- notificationSessionID = substitutions["SESSION_ID"].asUUID();
+ payload = notification->getPayload();
+ notificationObjectID = payload[payloadVariable].asUUID();
notificationName = notification->getName();
- if(notificationName == toastName
- && session_id == notificationSessionID)
+ if((notificationName == name)
+ && id == notificationObjectID)
{
itemsToRemove.push_back(it);
}
}
-
+
//Remove the notifications
if(itemsToRemove.size())
{
diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h
index fd7cc7ee82..6e68b0d1be 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.h
+++ b/indra/newview/lldonotdisturbnotificationstorage.h
@@ -49,6 +49,9 @@ class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotif
{
LOG_CLASS(LLDoNotDisturbNotificationStorage);
public:
+ static const char * toastName;
+ static const char * offerName;
+
LLDoNotDisturbNotificationStorage();
~LLDoNotDisturbNotificationStorage();
@@ -58,7 +61,7 @@ public:
void saveNotifications();
void loadNotifications();
void updateNotifications();
- void removeIMNotification(const LLUUID& session_id);
+ void removeNotification(const char * name, const LLUUID& id);
protected:
@@ -68,6 +71,7 @@ private:
LLNotificationChannelPtr getCommunicationChannel() const;
bool onChannelChanged(const LLSD& pPayload);
+ std::map<std::string, std::string> nameToPayloadParameterMap;
};
#endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index c93181c0a1..48e0caa0ce 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -152,7 +152,13 @@ void LLFloaterConversationPreview::showHistory()
chat.mSourceType = LLFloaterIMNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
}
- mChatHistory->appendMessage(chat);
+ LLSD chat_args;
+ chat_args["use_plain_text_chat_history"] =
+ gSavedSettings.getBOOL("PlainTextChatHistory");
+ chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime");
+ chat_args["show_names_for_p2p_conv"] = gSavedSettings.getBOOL("IMShowNamesForP2PConv");
+
+ mChatHistory->appendMessage(chat,chat_args);
}
}
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 8f290ae7c1..7e80237430 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -431,7 +431,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
return false;
}
LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id);
- LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id)));
+ LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ?
+ (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))
+ : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id)));
if (type == "remove_participant")
{
@@ -813,6 +815,10 @@ void LLFloaterIMContainer::onCustomAction(const LLSD& userdata)
floater_prefp->selectPrivacyPanel();
}
}
+ if ("Translating.Toggle" == command)
+ {
+ gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat"));
+ }
}
BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata)
@@ -843,7 +849,14 @@ BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata)
{
return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE);
}
-
+ if ("Translating.Enabled" == command)
+ {
+ return gSavedPerAccountSettings.getBOOL("TranslatingEnabled");
+ }
+ if ("Translating.On" == command)
+ {
+ return gSavedSettings.getBOOL("TranslateChat");
+ }
return FALSE;
}
@@ -1305,7 +1318,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
//Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal
if(gAgent.isDoNotDisturb() && session_id.notNull())
{
- LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id);
+ LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id);
}
}
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index bc5b8c334d..37404ab716 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -60,6 +60,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mInputEditorTopPad(0)
, mRefreshTimer(new LLTimer())
, mIsHostAttached(false)
+ , mHasVisibleBeenInitialized(false)
{
setAutoFocus(FALSE);
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
@@ -72,12 +73,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2));
mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable",
boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2));
- mEnableCallbackRegistrar.add("Translating.Enabled",
- boost::bind(&LLFloaterIMSessionTab::isTranslatingEnabled, this, _2));
- mEnableCallbackRegistrar.add("Translating.On",
- boost::bind(&LLFloaterIMSessionTab::isTranslationOn, this, _2));
- mCommitCallbackRegistrar.add("Translating.Toggle",
- boost::bind(&LLFloaterIMSessionTab::toggleTranslation, this, _2));
// Right click menu handling
mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2));
@@ -126,12 +121,14 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid
void LLFloaterIMSessionTab::setVisible(BOOL visible)
{
- LLTransientDockableFloater::setVisible(visible);
-
- if(visible)
+ if(visible && !mHasVisibleBeenInitialized)
{
- LLFloaterIMSessionTab::addToHost(mSessionID);
+ mHasVisibleBeenInitialized = true;
+ LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
+ LLFloaterIMSessionTab::addToHost(mSessionID);
}
+
+ LLTransientDockableFloater::setVisible(visible);
}
/*virtual*/
@@ -551,11 +548,6 @@ void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata)
LLFloaterIMSessionTab::processChatHistoryStyleUpdate();
}
-void LLFloaterIMSessionTab::toggleTranslation(const LLSD& userdata)
-{
- gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat"));
-}
-
bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata)
{
std::string item = userdata.asString();
@@ -579,16 +571,6 @@ bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata)
return (plain_text && (is_not_names || mIsP2PChat));
}
-bool LLFloaterIMSessionTab::isTranslatingEnabled(const LLSD& userdata)
-{
- return gSavedPerAccountSettings.getBOOL("TranslatingEnabled");
-}
-
-bool LLFloaterIMSessionTab::isTranslationOn(const LLSD& userdata)
-{
- return gSavedSettings.getBOOL("TranslateChat");
-}
-
void LLFloaterIMSessionTab::hideOrShowTitle()
{
const LLFloater::Params& default_params = LLFloater::getDefaultParams();
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 05da0f98bc..beaffc14a6 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -109,12 +109,8 @@ protected:
//
bool onIMShowModesMenuItemCheck(const LLSD& userdata);
bool onIMShowModesMenuItemEnable(const LLSD& userdata);
- bool isTranslatingEnabled(const LLSD& userdata);
- bool isTranslationOn(const LLSD& userdata);
static void onSlide(LLFloaterIMSessionTab *self);
- void toggleTranslation(const LLSD& userdata);
-
// refresh a visual state of the Call button
void updateCallBtnState(bool callIsActive);
@@ -186,6 +182,7 @@ private:
bool checkIfTornOff();
bool mIsHostAttached;
+ bool mHasVisibleBeenInitialized;
LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called.
};
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index d0a8dfc0c8..cb03c1d234 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -144,7 +144,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
args["FROM"] = av_name.getCompleteName();
args["FROM_ID"] = msg["from_id"];
args["SESSION_ID"] = msg["session_id"];
- LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
+ LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
void on_new_message(const LLSD& msg)
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 6474d56414..ad0a730dd1 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -46,6 +46,7 @@
#include "llappearancemgr.h"
#include "llappviewer.h"
#include "llclipboard.h"
+#include "lldonotdisturbnotificationstorage.h"
#include "llfloaterinventory.h"
#include "llfloatersidepanelcontainer.h"
#include "llfocusmgr.h"
@@ -1132,11 +1133,37 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
}
}
+void LLInventoryAction::removeItemFromDND(LLFolderView* root)
+{
+ if(gAgent.isDoNotDisturb())
+ {
+ //Get selected items
+ LLFolderView::selected_items_t selectedItems = root->getSelectedItems();
+ LLFolderViewModelItemInventory * viewModel = NULL;
+
+ //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification
+ //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification.
+ for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+ {
+ viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem());
+
+ if(viewModel && viewModel->getUUID().notNull())
+ {
+ //Will remove the item offer notification
+ LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID());
+ }
+ }
+ }
+}
+
void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root )
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
+ //Need to remove item from DND before item is removed from root folder view
+ //because once removed from root folder view the item is no longer a selected item
+ removeItemFromDND(root);
root->removeSelectedItems();
}
}
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 11fc17ce9b..f1066a4dc9 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -433,6 +433,7 @@ struct LLInventoryAction
static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root);
+ static void removeItemFromDND(LLFolderView* root);
};
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2d5634a41d..36ddf26c82 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2503,22 +2503,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
return TRUE;
}
- LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
+ LLFloater* focused_floaterp = gFloaterView->getFocusedFloater();
+ std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : "");
- // Traverses up the hierarchy
if( keyboard_focus )
{
- if (nearby_chat)
- {
- LLChatEntry* chat_editor = nearby_chat->getChatBox();
-
- // arrow keys move avatar while chatting hack
- if (chat_editor && chat_editor->hasFocus())
+ if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel"))
{
- // If text field is empty, there's no point in trying to move
- // cursor with arrow keys, so allow movement
- if (chat_editor->getText().empty()
- || gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
+ if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
{
// let Control-Up and Control-Down through for chat line history,
if (!(key == KEY_UP && mask == MASK_CONTROL)
@@ -2540,7 +2532,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
break;
}
}
- }
}
}
@@ -2575,6 +2566,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
{
// Initialize nearby chat if it's missing
+ LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (!nearby_chat)
{
LLSD name("im_container");
diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml
index f2a8b39b04..b0adca0e0e 100644
--- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml
+++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml
@@ -45,22 +45,5 @@
<menu_item_check.on_enable
function="IMSession.Menu.ShowModes.Enable"
parameter="IMShowNamesForP2PConv" />
- </menu_item_check>
- <menu_item_separator layout="topleft" />
- <menu_item_check name="Translate_chat" label="Translate chat">
- <menu_item_check.on_click
- function="Translating.Toggle" />
- <menu_item_check.on_check
- function="Translating.On" />
- <menu_item_check.on_enable
- function="Translating.Enabled" />
- </menu_item_check>
- <menu_item_check name="Translation_settings" label="Translation settings...">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="prefs_translation" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="prefs_translation" />
- </menu_item_check>
+ </menu_item_check>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml
index 2f2bafb95d..7ea87ee05c 100644
--- a/indra/newview/skins/default/xui/en/menu_participant_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml
@@ -89,4 +89,24 @@
function="Avatar.EnableItem"
parameter="conversation_log" />
</menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_check name="Translate_chat" label="Translate Nearby chat">
+ <menu_item_check.on_click
+ function="IMFloaterContainer.Action"
+ parameter="Translating.Toggle" />
+ <menu_item_check.on_check
+ function="IMFloaterContainer.Check"
+ parameter="Translating.On" />
+ <menu_item_check.on_enable
+ function="IMFloaterContainer.Check"
+ parameter="Translating.Enabled" />
+ </menu_item_check>
+ <menu_item_check name="Translation_settings" label="Translation settings...">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="prefs_translation" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="prefs_translation" />
+ </menu_item_check>
</toggleable_menu>