mirror of https://github.com/aseprite/aseprite.git
				
				
				
			
		
			
				
	
	
		
			182 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Aseprite
 | |
| // Copyright (C) 2022  Igara Studio S.A.
 | |
| //
 | |
| // This program is distributed under the terms of
 | |
| // the End-User License Agreement for Aseprite.
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
|   #include "config.h"
 | |
| #endif
 | |
| 
 | |
| #include "app/ui/layout.h"
 | |
| 
 | |
| #include "app/app.h"
 | |
| #include "app/ui/color_bar.h"
 | |
| #include "app/ui/context_bar.h"
 | |
| #include "app/ui/dock.h"
 | |
| #include "app/ui/main_window.h"
 | |
| #include "app/ui/status_bar.h"
 | |
| #include "app/ui/timeline/timeline.h"
 | |
| #include "app/ui/toolbar.h"
 | |
| #include "app/ui/workspace.h"
 | |
| #include "app/xml_document.h"
 | |
| #include "app/xml_exception.h"
 | |
| #include "base/convert_to.h"
 | |
| #include "ui/widget.h"
 | |
| 
 | |
| #include <cstring>
 | |
| #include <sstream>
 | |
| 
 | |
| namespace app {
 | |
| 
 | |
| static void save_dock_layout(TiXmlElement* elem, const Dock* dock)
 | |
| {
 | |
|   for (const auto child : dock->children()) {
 | |
|     const int side = dock->whichSideChildIsDocked(child);
 | |
|     const gfx::Size size = dock->getUserDefinedSizeAtSide(side);
 | |
| 
 | |
|     std::string sideStr;
 | |
|     switch (side) {
 | |
|       case ui::LEFT:   sideStr = "left"; break;
 | |
|       case ui::RIGHT:  sideStr = "right"; break;
 | |
|       case ui::TOP:    sideStr = "top"; break;
 | |
|       case ui::BOTTOM: sideStr = "bottom"; break;
 | |
|       case ui::CENTER:
 | |
|         // Empty side attribute
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     TiXmlElement childElem("");
 | |
| 
 | |
|     if (auto subdock = dynamic_cast<const Dock*>(child)) {
 | |
|       childElem.SetValue("dock");
 | |
|       if (!sideStr.empty())
 | |
|         childElem.SetAttribute("side", sideStr);
 | |
| 
 | |
|       save_dock_layout(&childElem, subdock);
 | |
|     }
 | |
|     else {
 | |
|       // Set the widget ID as the element name, e.g. <timeline />,
 | |
|       // <colorbar />, etc.
 | |
|       childElem.SetValue(child->id());
 | |
|       if (!sideStr.empty())
 | |
|         childElem.SetAttribute("side", sideStr);
 | |
|       if (size.w)
 | |
|         childElem.SetAttribute("width", size.w);
 | |
|       if (size.h)
 | |
|         childElem.SetAttribute("height", size.h);
 | |
|     }
 | |
| 
 | |
|     elem->InsertEndChild(childElem);
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void load_dock_layout(const TiXmlElement* elem, Dock* dock)
 | |
| {
 | |
|   const char* elemNameStr = elem->Value();
 | |
|   if (!elemNameStr) {
 | |
|     ASSERT(false); // Impossible?
 | |
|     return;
 | |
|   }
 | |
|   const std::string elemName = elemNameStr;
 | |
| 
 | |
|   MainWindow* win = App::instance()->mainWindow();
 | |
|   ASSERT(win);
 | |
| 
 | |
|   ui::Widget* widget = nullptr;
 | |
|   Dock* subdock = nullptr;
 | |
| 
 | |
|   int side = ui::CENTER;
 | |
|   if (auto sideStr = elem->Attribute("side")) {
 | |
|     if (std::strcmp(sideStr, "left") == 0)
 | |
|       side = ui::LEFT;
 | |
|     if (std::strcmp(sideStr, "right") == 0)
 | |
|       side = ui::RIGHT;
 | |
|     if (std::strcmp(sideStr, "top") == 0)
 | |
|       side = ui::TOP;
 | |
|     if (std::strcmp(sideStr, "bottom") == 0)
 | |
|       side = ui::BOTTOM;
 | |
|   }
 | |
| 
 | |
|   const char* widthStr = elem->Attribute("width");
 | |
|   const char* heightStr = elem->Attribute("height");
 | |
|   gfx::Size size;
 | |
|   if (widthStr)
 | |
|     size.w = base::convert_to<int>(std::string(widthStr));
 | |
|   if (heightStr)
 | |
|     size.h = base::convert_to<int>(std::string(heightStr));
 | |
| 
 | |
|   if (elemName == "colorbar") {
 | |
|     widget = win->colorBar();
 | |
|   }
 | |
|   else if (elemName == "contextbar") {
 | |
|     widget = win->getContextBar();
 | |
|   }
 | |
|   else if (elemName == "timeline") {
 | |
|     widget = win->getTimeline();
 | |
|   }
 | |
|   else if (elemName == "toolbar") {
 | |
|     widget = win->toolBar();
 | |
|   }
 | |
|   else if (elemName == "workspace") {
 | |
|     widget = win->getWorkspace();
 | |
|   }
 | |
|   else if (elemName == "statusbar") {
 | |
|     widget = win->statusBar();
 | |
|   }
 | |
|   else if (elemName == "dock") {
 | |
|     subdock = dock->subdock(side);
 | |
|   }
 | |
| 
 | |
|   if (subdock) {
 | |
|     auto childElem = elem->FirstChildElement();
 | |
|     while (childElem) {
 | |
|       load_dock_layout(childElem, subdock);
 | |
|       childElem = childElem->NextSiblingElement();
 | |
|     }
 | |
|   }
 | |
|   else {
 | |
|     dock->dock(side, widget, size);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // static
 | |
| LayoutPtr Layout::MakeFromXmlElement(const TiXmlElement* layoutElem)
 | |
| {
 | |
|   auto layout = std::make_shared<Layout>();
 | |
|   if (auto name = layoutElem->Attribute("name"))
 | |
|     layout->m_name = name;
 | |
| 
 | |
|   layout->m_elem.reset(layoutElem->Clone()->ToElement());
 | |
|   return layout;
 | |
| }
 | |
| 
 | |
| // static
 | |
| LayoutPtr Layout::MakeFromDock(const std::string& name, const Dock* dock)
 | |
| {
 | |
|   auto layout = std::make_shared<Layout>();
 | |
|   layout->m_name = name;
 | |
| 
 | |
|   layout->m_elem = std::make_unique<TiXmlElement>("layout");
 | |
|   layout->m_elem->SetAttribute("name", name);
 | |
|   save_dock_layout(layout->m_elem.get(), dock);
 | |
| 
 | |
|   return layout;
 | |
| }
 | |
| 
 | |
| bool Layout::loadLayout(Dock* dock) const
 | |
| {
 | |
|   if (!m_elem)
 | |
|     return false;
 | |
| 
 | |
|   TiXmlElement* elem = m_elem->FirstChildElement();
 | |
|   while (elem) {
 | |
|     load_dock_layout(elem, dock);
 | |
|     elem = elem->NextSiblingElement();
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| } // namespace app
 |