mirror of https://github.com/aseprite/aseprite.git
Add option to save/restore user-defined layouts on memory
This happens only in memory at the moment (layouts are not saved in disk yet), and the customization is quite simple (only size of splitters, timeline position). But in the future we should be able to dock elements in any place.
This commit is contained in:
parent
381d9e663a
commit
dc51ca25e0
|
@ -1236,6 +1236,11 @@ name = Name:
|
|||
tileset = Tileset:
|
||||
default_new_layer_name = New Layer
|
||||
|
||||
[new_layout]
|
||||
title = New UI Layout
|
||||
name = Name:
|
||||
default_name = User Layout
|
||||
|
||||
[news_listbox]
|
||||
more = More...
|
||||
problem_loading = Problems loading news. Please retry.
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2022 by Igara Studio S.A. -->
|
||||
<gui>
|
||||
<window id="new_layout" text="@.title">
|
||||
<vbox>
|
||||
<hbox>
|
||||
<label text="@.name" />
|
||||
<entry id="name" text="@.default_name"
|
||||
maxsize="128" expansive="true"
|
||||
magnet="true" />
|
||||
</hbox>
|
||||
|
||||
<separator horizontal="true" />
|
||||
|
||||
<hbox homogeneous="true" cell_align="right">
|
||||
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
||||
<button text="@general.cancel" closewindow="true" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
</gui>
|
|
@ -654,6 +654,7 @@ target_sources(app-lib PRIVATE
|
|||
ui/input_chain.cpp
|
||||
ui/keyboard_shortcuts.cpp
|
||||
ui/layer_frame_comboboxes.cpp
|
||||
ui/layout.cpp
|
||||
ui/layout_selector.cpp
|
||||
ui/main_menu_bar.cpp
|
||||
ui/main_window.cpp
|
||||
|
|
|
@ -41,6 +41,17 @@ int side_index(int side)
|
|||
return kCenterIndex; // ui::CENTER
|
||||
}
|
||||
|
||||
int side_from_index(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case kTopIndex: return ui::TOP;
|
||||
case kBottomIndex: return ui::BOTTOM;
|
||||
case kLeftIndex: return ui::LEFT;
|
||||
case kRightIndex: return ui::RIGHT;
|
||||
}
|
||||
return ui::CENTER; // kCenterIndex
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void DockTabs::onSizeHint(ui::SizeHintEvent& ev)
|
||||
|
@ -202,6 +213,25 @@ void Dock::undock(Widget* widget)
|
|||
}
|
||||
}
|
||||
|
||||
int Dock::whichSideChildIsDocked(const ui::Widget* widget) const
|
||||
{
|
||||
for (int i = 0; i < kSides; ++i)
|
||||
if (m_sides[i] == widget)
|
||||
return side_from_index(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gfx::Size Dock::getUserDefinedSizeAtSide(int side) const
|
||||
{
|
||||
int i = side_index(side);
|
||||
// Only EXPANSIVE sides can be user-defined (has a splitter so the
|
||||
// user can expand or shrink it)
|
||||
if (m_aligns[i] & EXPANSIVE)
|
||||
return m_sizes[i];
|
||||
else
|
||||
return gfx::Size();
|
||||
}
|
||||
|
||||
Dock* Dock::subdock(int side)
|
||||
{
|
||||
int i = side_index(side);
|
||||
|
@ -431,6 +461,7 @@ void Dock::forEachSide(gfx::Rect bounds,
|
|||
int spacing = (m_aligns[i] & EXPANSIVE ? childSpacing() : 0);
|
||||
|
||||
const gfx::Size sz = (m_aligns[i] & EXPANSIVE ? m_sizes[i] : widget->sizeHint());
|
||||
|
||||
gfx::Rect rc, separator;
|
||||
switch (i) {
|
||||
case kTopIndex:
|
||||
|
|
|
@ -53,6 +53,10 @@ public:
|
|||
Dock* right() { return subdock(ui::RIGHT); }
|
||||
Dock* center() { return subdock(ui::CENTER); }
|
||||
|
||||
// Functions useful to query/save the dock layout.
|
||||
int whichSideChildIsDocked(const ui::Widget* widget) const;
|
||||
gfx::Size getUserDefinedSizeAtSide(int side) const;
|
||||
|
||||
obs::signal<void()> Resize;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
// 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/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 == "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);
|
||||
}
|
||||
}
|
||||
|
||||
Layout::Layout(const std::string& name, const Dock* dock) : m_name(name)
|
||||
{
|
||||
XmlDocumentRef doc(new TiXmlDocument());
|
||||
TiXmlElement layoutsElem("layouts");
|
||||
{
|
||||
TiXmlElement layoutElem("layout");
|
||||
layoutElem.SetAttribute("name", name);
|
||||
|
||||
save_dock_layout(layoutElem, dock);
|
||||
|
||||
layoutsElem.InsertEndChild(layoutElem);
|
||||
}
|
||||
|
||||
TiXmlDeclaration declaration("1.0", "utf-8", "");
|
||||
doc->InsertEndChild(declaration);
|
||||
doc->InsertEndChild(layoutsElem);
|
||||
|
||||
std::stringstream s;
|
||||
s << *doc;
|
||||
m_data = s.str();
|
||||
}
|
||||
|
||||
bool Layout::loadLayout(Dock* dock) const
|
||||
{
|
||||
XmlDocumentRef doc(new TiXmlDocument);
|
||||
doc->Parse(m_data.c_str(), 0, TIXML_DEFAULT_ENCODING);
|
||||
TiXmlHandle handle(doc.get());
|
||||
|
||||
TiXmlElement* layoutElem = handle.FirstChild("layouts").FirstChild("layout").ToElement();
|
||||
|
||||
if (!layoutElem)
|
||||
return false;
|
||||
|
||||
TiXmlElement* elem = layoutElem->FirstChildElement();
|
||||
while (elem) {
|
||||
load_dock_layout(elem, dock);
|
||||
elem = elem->NextSiblingElement();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace app
|
|
@ -0,0 +1,35 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UI_LAYOUT_H_INCLUDED
|
||||
#define APP_UI_LAYOUT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
class Dock;
|
||||
|
||||
class Layout {
|
||||
public:
|
||||
Layout(const std::string& name, const Dock* dock);
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::string& data() const { return m_data; }
|
||||
|
||||
bool loadLayout(Dock* dock) const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_data;
|
||||
};
|
||||
|
||||
using LayoutPtr = std::shared_ptr<Layout>;
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
|
@ -17,10 +17,13 @@
|
|||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/separator_in_view.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/tooltips.h"
|
||||
#include "ui/window.h"
|
||||
|
||||
#include "new_layout.xml.h"
|
||||
|
||||
#define ANI_TICKS 5
|
||||
|
||||
namespace app {
|
||||
|
@ -30,29 +33,6 @@ using namespace ui;
|
|||
|
||||
namespace {
|
||||
|
||||
enum class LayoutId { DEFAULT, DEFAULT_MIRROR, CUSTOMIZE };
|
||||
|
||||
class LayoutItem : public ListItem {
|
||||
public:
|
||||
LayoutItem(const LayoutId id, const std::string& text) : ListItem(text), m_id(id) {}
|
||||
|
||||
void select()
|
||||
{
|
||||
MainWindow* win = App::instance()->mainWindow();
|
||||
|
||||
switch (m_id) {
|
||||
case LayoutId::DEFAULT: win->setDefaultLayout(); break;
|
||||
case LayoutId::DEFAULT_MIRROR: win->setDefaultMirrorLayout(); break;
|
||||
case LayoutId::CUSTOMIZE:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LayoutId m_id;
|
||||
};
|
||||
|
||||
// TODO Similar ButtonSet to the one in timeline_conf.xml
|
||||
class TimelineButtons : public ButtonSet {
|
||||
public:
|
||||
|
@ -65,7 +45,7 @@ public:
|
|||
auto& timelinePosOption = Preferences::instance().general.timelinePosition;
|
||||
|
||||
setSelectedButtonFromTimelinePosition(timelinePosOption());
|
||||
timelinePosOption.AfterChange.connect(
|
||||
m_timelinePosConn = timelinePosOption.AfterChange.connect(
|
||||
[this](gen::TimelinePosition position) { setSelectedButtonFromTimelinePosition(position); });
|
||||
|
||||
InitTheme.connect([this] {
|
||||
|
@ -95,14 +75,96 @@ private:
|
|||
// Show the timeline
|
||||
App::instance()->mainWindow()->setTimelineVisibility(true);
|
||||
}
|
||||
|
||||
obs::scoped_connection m_timelinePosConn;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
class LayoutSelector::LayoutItem : public ListItem {
|
||||
public:
|
||||
enum LayoutId {
|
||||
DEFAULT,
|
||||
DEFAULT_MIRROR,
|
||||
SAVE_LAYOUT,
|
||||
USER_DEFINED,
|
||||
};
|
||||
|
||||
LayoutItem(LayoutSelector* selector,
|
||||
const LayoutId id,
|
||||
const std::string& text,
|
||||
const LayoutPtr layout = nullptr)
|
||||
: ListItem(text)
|
||||
, m_selector(selector)
|
||||
, m_id(id)
|
||||
, m_layout(layout)
|
||||
{
|
||||
ASSERT((id != USER_DEFINED && layout == nullptr) || (id == USER_DEFINED && layout != nullptr));
|
||||
}
|
||||
|
||||
void selectImmediately()
|
||||
{
|
||||
MainWindow* win = App::instance()->mainWindow();
|
||||
|
||||
switch (m_id) {
|
||||
case LayoutId::DEFAULT: win->setDefaultLayout(); break;
|
||||
case LayoutId::DEFAULT_MIRROR: win->setDefaultMirrorLayout(); break;
|
||||
case LayoutId::USER_DEFINED:
|
||||
ASSERT(m_layout);
|
||||
if (m_layout)
|
||||
win->loadUserLayout(m_layout.get());
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void selectAfterClose()
|
||||
{
|
||||
MainWindow* win = App::instance()->mainWindow();
|
||||
|
||||
switch (m_id) {
|
||||
case LayoutId::SAVE_LAYOUT: {
|
||||
gen::NewLayout window;
|
||||
window.name()->setText(
|
||||
fmt::format("{} ({})", window.name()->text(), m_selector->m_layouts.size()));
|
||||
|
||||
window.openWindowInForeground();
|
||||
if (window.closer() == window.ok()) {
|
||||
auto layout = std::make_shared<Layout>(window.name()->text(), win->customizableDock());
|
||||
|
||||
m_selector->addLayout(std::move(layout));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LayoutId m_id;
|
||||
LayoutSelector* m_selector;
|
||||
LayoutPtr m_layout;
|
||||
};
|
||||
|
||||
void LayoutSelector::LayoutComboBox::onChange()
|
||||
{
|
||||
ComboBox::onChange();
|
||||
if (auto item = dynamic_cast<LayoutItem*>(getSelectedItem())) {
|
||||
item->select();
|
||||
item->selectImmediately();
|
||||
m_selected = item;
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSelector::LayoutComboBox::onCloseListBox()
|
||||
{
|
||||
ComboBox::onCloseListBox();
|
||||
if (m_selected) {
|
||||
m_selected->selectAfterClose();
|
||||
m_selected = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +193,16 @@ LayoutSelector::~LayoutSelector()
|
|||
stopAnimation();
|
||||
}
|
||||
|
||||
void LayoutSelector::addLayout(const LayoutPtr& layout)
|
||||
{
|
||||
auto item = m_comboBox.addItem(
|
||||
new LayoutItem(this, LayoutItem::USER_DEFINED, layout->name(), layout));
|
||||
|
||||
m_layouts.push_back(layout);
|
||||
|
||||
m_comboBox.setSelectedItemIndex(item);
|
||||
}
|
||||
|
||||
void LayoutSelector::onAnimationFrame()
|
||||
{
|
||||
switch (animation()) {
|
||||
|
@ -171,10 +243,15 @@ void LayoutSelector::switchSelector()
|
|||
// Create the combobox for first time
|
||||
if (m_comboBox.getItemCount() == 0) {
|
||||
m_comboBox.addItem(new SeparatorInView("Layout", HORIZONTAL));
|
||||
m_comboBox.addItem(new LayoutItem(LayoutId::DEFAULT, "Default"));
|
||||
m_comboBox.addItem(new LayoutItem(LayoutId::DEFAULT_MIRROR, "Default / Mirror"));
|
||||
m_comboBox.addItem(new LayoutItem(this, LayoutItem::DEFAULT, "Default"));
|
||||
m_comboBox.addItem(new LayoutItem(this, LayoutItem::DEFAULT_MIRROR, "Default / Mirror"));
|
||||
m_comboBox.addItem(new SeparatorInView("Timeline", HORIZONTAL));
|
||||
m_comboBox.addItem(new TimelineButtons());
|
||||
m_comboBox.addItem(new SeparatorInView("User Layouts", HORIZONTAL));
|
||||
m_comboBox.addItem(new LayoutItem(this, LayoutItem::SAVE_LAYOUT, "Save..."));
|
||||
for (const auto& layout : m_layouts) {
|
||||
m_comboBox.addItem(new LayoutItem(this, LayoutItem::USER_DEFINED, layout->name(), layout));
|
||||
}
|
||||
}
|
||||
|
||||
m_comboBox.setVisible(true);
|
||||
|
|
|
@ -10,11 +10,13 @@
|
|||
|
||||
#include "app/ui/dockable.h"
|
||||
#include "app/ui/icon_button.h"
|
||||
#include "app/ui/layout.h"
|
||||
#include "ui/animated_widget.h"
|
||||
#include "ui/box.h"
|
||||
#include "ui/combobox.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
class TooltipManager;
|
||||
|
@ -31,14 +33,21 @@ class LayoutSelector : public ui::HBox,
|
|||
ANI_COLLAPSING,
|
||||
};
|
||||
|
||||
class LayoutItem;
|
||||
|
||||
class LayoutComboBox : public ui::ComboBox {
|
||||
private:
|
||||
void onChange() override;
|
||||
void onCloseListBox() override;
|
||||
LayoutItem* m_selected = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
LayoutSelector(ui::TooltipManager* tooltipManager);
|
||||
~LayoutSelector();
|
||||
|
||||
void addLayout(const LayoutPtr& layout);
|
||||
|
||||
// Dockable impl
|
||||
int dockableAt() const override { return ui::TOP | ui::BOTTOM; }
|
||||
|
||||
|
@ -52,6 +61,7 @@ private:
|
|||
IconButton m_button;
|
||||
gfx::Size m_startSize;
|
||||
gfx::Size m_endSize;
|
||||
std::vector<LayoutPtr> m_layouts;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
|
|
@ -156,6 +156,14 @@ void MainWindow::initialize()
|
|||
m_workspace->setExpansive(true);
|
||||
m_notifications->setVisible(false);
|
||||
|
||||
// IDs to create UI layouts from a Dock (see app::Layout
|
||||
// constructor).
|
||||
m_colorBar->setId("colorbar");
|
||||
m_contextBar->setId("contextbar");
|
||||
m_timeline->setId("timeline");
|
||||
m_toolBar->setId("toolbar");
|
||||
m_workspace->setId("workspace");
|
||||
|
||||
// Add the widgets in the boxes
|
||||
addChild(m_tooltipManager);
|
||||
addChild(m_dock);
|
||||
|
@ -419,6 +427,19 @@ void MainWindow::setDefaultMirrorLayout()
|
|||
configureWorkspaceLayout();
|
||||
}
|
||||
|
||||
void MainWindow::loadUserLayout(const Layout* layout)
|
||||
{
|
||||
m_timelineResizeConn.disconnect();
|
||||
m_colorBarResizeConn.disconnect();
|
||||
|
||||
m_customizableDock->resetDocks();
|
||||
|
||||
if (!layout->loadLayout(m_customizableDock))
|
||||
setDefaultLayout();
|
||||
|
||||
this->layout();
|
||||
}
|
||||
|
||||
void MainWindow::dataRecoverySessionsAreReady()
|
||||
{
|
||||
getHomeView()->dataRecoverySessionsAreReady();
|
||||
|
|
|
@ -34,8 +34,9 @@ class DocView;
|
|||
class Dock;
|
||||
class HomeView;
|
||||
class INotificationDelegate;
|
||||
class MainMenuBar;
|
||||
class Layout;
|
||||
class LayoutSelector;
|
||||
class MainMenuBar;
|
||||
class Notifications;
|
||||
class PreviewEditorWindow;
|
||||
class StatusBar;
|
||||
|
@ -56,12 +57,15 @@ public:
|
|||
MainWindow();
|
||||
~MainWindow();
|
||||
|
||||
// TODO refactor: remove the get prefix from these functions
|
||||
MainMenuBar* getMenuBar() { return m_menuBar.get(); }
|
||||
ContextBar* getContextBar() { return m_contextBar.get(); }
|
||||
StatusBar* statusBar() { return m_statusBar.get(); }
|
||||
WorkspaceTabs* getTabsBar() { return m_tabsBar.get(); }
|
||||
Timeline* getTimeline() { return m_timeline.get(); }
|
||||
Workspace* getWorkspace() { return m_workspace.get(); }
|
||||
ColorBar* colorBar() { return m_colorBar.get(); }
|
||||
ToolBar* toolBar() { return m_toolBar.get(); }
|
||||
PreviewEditorWindow* getPreviewEditor() { return m_previewEditor.get(); }
|
||||
#ifdef ENABLE_UPDATER
|
||||
CheckUpdateDelegate* getCheckUpdateDelegate();
|
||||
|
@ -89,6 +93,8 @@ public:
|
|||
|
||||
void setDefaultLayout();
|
||||
void setDefaultMirrorLayout();
|
||||
void loadUserLayout(const Layout* layout);
|
||||
const Dock* customizableDock() const { return m_customizableDock; }
|
||||
|
||||
// When crash::DataRecovery finish to search for sessions, this
|
||||
// function is called.
|
||||
|
|
Loading…
Reference in New Issue