/* * This source file is part of libRocket, the HTML/CSS Interface Middleware * * For the latest information, see http://www.librocket.com * * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include "../../Include/Rocket/Controls/ElementTabSet.h" #include "../../Include/Rocket/Core/Math.h" #include "../../Include/Rocket/Core/Factory.h" namespace Rocket { namespace Controls { ElementTabSet::ElementTabSet(const Rocket::Core::String& tag) : Core::Element(tag) { active_tab = 0; } ElementTabSet::~ElementTabSet() { } // Sets the specifed tab index's tab title RML. void ElementTabSet::SetTab(int tab_index, const Rocket::Core::String& rml) { Core::Element* element = Core::Factory::InstanceElement(NULL, "*", "tab", Rocket::Core::XMLAttributes()); Core::Factory::InstanceElementText(element, rml); SetTab(tab_index, element); element->RemoveReference(); } // Sets the specifed tab index's tab panel RML. void ElementTabSet::SetPanel(int tab_index, const Rocket::Core::String& rml) { Core::Element* element = Core::Factory::InstanceElement(NULL, "*", "panel", Rocket::Core::XMLAttributes()); Core::Factory::InstanceElementText(element, rml); SetPanel(tab_index, element); element->RemoveReference(); } // Set the specifed tab index's title element. void ElementTabSet::SetTab(int tab_index, Core::Element* element) { Core::Element* tabs = GetChildByTag("tabs"); if (tab_index >= 0 && tab_index < tabs->GetNumChildren()) tabs->ReplaceChild(GetChild(tab_index), element); else tabs->AppendChild(element); } // Set the specified tab index's body element. void ElementTabSet::SetPanel(int tab_index, Core::Element* element) { // Append the window Core::Element* windows = GetChildByTag("panels"); if (tab_index >= 0 && tab_index < windows->GetNumChildren()) windows->ReplaceChild(GetChild(tab_index), element); else windows->AppendChild(element); } // Remove one of the tab set's panels and its corresponding tab. void ElementTabSet::RemoveTab(int tab_index) { if (tab_index < 0) return; Core::Element* panels = GetChildByTag("panels"); Core::Element* tabs = GetChildByTag("tabs"); if (panels->GetNumChildren() > tab_index && tabs->GetNumChildren() > tab_index) { panels->RemoveChild(panels->GetChild(tab_index)); tabs->RemoveChild(tabs->GetChild(tab_index)); } } // Retrieve the number of tabs in the tabset. int ElementTabSet::GetNumTabs() { return GetChildByTag("tabs")->GetNumChildren(); } void ElementTabSet::SetActiveTab(int tab_index) { // Update display if the tab has changed if (tab_index != active_tab) { Core::Element* tabs = GetChildByTag("tabs"); Core::Element* old_tab = tabs->GetChild(active_tab); Core::Element* new_tab = tabs->GetChild(tab_index); if (old_tab) old_tab->SetPseudoClass("selected", false); if (new_tab) new_tab->SetPseudoClass("selected", true); Core::Element* windows = GetChildByTag("panels"); Core::Element* old_window = windows->GetChild(active_tab); Core::Element* new_window = windows->GetChild(tab_index); if (old_window) old_window->SetProperty("display", "none"); if (new_window) new_window->SetProperty("display", "inline-block"); active_tab = tab_index; Rocket::Core::Dictionary parameters; parameters.emplace("tab_index", active_tab); DispatchEvent("tabchange", parameters); } } int ElementTabSet::GetActiveTab() const { return active_tab; } // Process the incoming event. void ElementTabSet::ProcessEvent(Core::Event& event) { Core::Element::ProcessEvent(event); if (event.GetCurrentElement() == this && event == "click") { // Find the tab that this click occured on Core::Element* tabs = GetChildByTag("tabs"); Core::Element* tab = event.GetTargetElement(); while (tab && tab != this && tab->GetParentNode() != tabs) tab = tab->GetParentNode(); // Abort if we couldn't find the tab the click occured on if (!tab || tab == this) return; // Determine the new active tab index int new_active_tab = active_tab; for (int i = 0; i < tabs->GetNumChildren(); i++) { if (tabs->GetChild(i) == tab) { new_active_tab = i; break; } } SetActiveTab(new_active_tab); } } void ElementTabSet::OnChildAdd(Core::Element* child) { Core::Element::OnChildAdd(child); if (child->GetParentNode() == GetChildByTag("tabs")) { // Set up the new button and append it child->SetProperty("display", "inline-block"); child->AddEventListener("click", this); if (child->GetParentNode()->GetChild(active_tab) == child) child->SetPseudoClass("selected", true); } if (child->GetParentNode() == GetChildByTag("panels")) { // Hide the new tab window child->SetProperty("display", "none"); // Make the new element visible if its the active tab if (child->GetParentNode()->GetChild(active_tab) == child) child->SetProperty("display", "inline-block"); } } void ElementTabSet::OnChildRemove(Core::Element* child) { Core::Element::OnChildRemove(child); // If its a tab, remove its event listener if (child->GetParentNode() == GetChildByTag("tabs")) { child->RemoveEventListener("click", this); } } Core::Element* ElementTabSet::GetChildByTag(const Rocket::Core::String& tag) { // Look for the existing child for (int i = 0; i < GetNumChildren(); i++) { if (GetChild(i)->GetTagName() == tag) return GetChild(i); } // If it doesn't exist, create it Core::Element* element = Core::Factory::InstanceElement(this, "*", tag, Rocket::Core::XMLAttributes()); AppendChild(element); element->RemoveReference(); return element; } void ElementTabSet::OnAttach(Core::Element * ROCKET_UNUSED_PARAMETER(element)) { ROCKET_UNUSED(element); AddReference(); } void ElementTabSet::OnDetach(Core::Element * ROCKET_UNUSED_PARAMETER(element)) { ROCKET_UNUSED(element); RemoveReference(); } } }