mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-16 05:42:32 +00:00
Merge branch 'master' into beta
This commit is contained in:
commit
0014673e41
@ -451,6 +451,8 @@ if(NOT USE_STATIC_LIBC)
|
||||
endif()
|
||||
|
||||
set(LAF_WITH_TESTS ${ENABLE_TESTS} CACHE BOOL "Enable LAF tests")
|
||||
set(UNDO_TESTS ${ENABLE_TESTS} CACHE BOOL "Enable undo tests")
|
||||
|
||||
add_subdirectory(laf)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
@ -96,6 +96,7 @@
|
||||
<option id="screen_scale" type="int" default="0" />
|
||||
<option id="ui_scale" type="int" default="1" migrate="experimental.ui_scale" />
|
||||
<option id="gpu_acceleration" type="bool" default="false" />
|
||||
<option id="show_home" type="bool" default="true" />
|
||||
<option id="visible_timeline" type="bool" default="false" />
|
||||
<option id="autoshow_timeline" type="bool" default="true" migrate="Options.AutoShowTimeline" />
|
||||
<option id="rewind_on_stop" type="bool" default="false" />
|
||||
|
@ -441,6 +441,11 @@
|
||||
<text color="link_hover" />
|
||||
</style>
|
||||
|
||||
<!-- browser_link -->
|
||||
<style id="browser_link" base="link">
|
||||
<text padding-top="1" />
|
||||
</style>
|
||||
|
||||
<!-- view -->
|
||||
<style id="view">
|
||||
<background part="sunken_normal" />
|
||||
|
@ -40,6 +40,7 @@
|
||||
</grid>
|
||||
</hbox>
|
||||
<check text="GPU acceleration" id="gpu_acceleration" tooltip="Check this option to enable hardware acceleration" />
|
||||
<check text="Show Home tab when Aseprite is started" id="show_home" />
|
||||
<check text="Expand menu bar items on mouseover" id="expand_menubar_on_mouseover" tooltip="Check this option to get this old menus behavior." />
|
||||
<hbox>
|
||||
<check text="Automatically save recovery data every" id="enable_data_recovery" tooltip="With this option you can recover your documents if the program finalizes unexpectedly." />
|
||||
|
@ -196,6 +196,8 @@ public:
|
||||
gpuAcceleration()->setVisible(false);
|
||||
}
|
||||
|
||||
showHome()->setSelected(m_pref.general.showHome());
|
||||
|
||||
// Right-click
|
||||
|
||||
static_assert(int(app::gen::RightClickMode::PAINT_BGCOLOR) == 0, "");
|
||||
@ -356,6 +358,10 @@ public:
|
||||
reset_screen = true;
|
||||
}
|
||||
|
||||
bool newShowHome = showHome()->isSelected();
|
||||
if (newShowHome != m_pref.general.showHome())
|
||||
m_pref.general.showHome(newShowHome);
|
||||
|
||||
m_pref.save();
|
||||
|
||||
if (!warnings.empty()) {
|
||||
|
@ -447,8 +447,12 @@ private:
|
||||
Label* label;
|
||||
|
||||
if (word.size() > 4 &&
|
||||
std::strncmp(word.c_str(), "http", 4) == 0)
|
||||
std::strncmp(word.c_str(), "http", 4) == 0) {
|
||||
label = new LinkLabel(word);
|
||||
label->setProperty(
|
||||
SkinStylePropertyPtr(
|
||||
new SkinStyleProperty(SkinTheme::instance()->styles.browserLink())));
|
||||
}
|
||||
else
|
||||
label = new Label(word);
|
||||
|
||||
@ -474,6 +478,9 @@ private:
|
||||
|
||||
void addLink(const std::string& url, const std::string& text) {
|
||||
auto label = new LinkLabel(url, text);
|
||||
label->setProperty(
|
||||
SkinStylePropertyPtr(
|
||||
new SkinStyleProperty(SkinTheme::instance()->styles.browserLink())));
|
||||
|
||||
if (url.find(':') == std::string::npos) {
|
||||
label->setUrl("");
|
||||
|
@ -229,6 +229,12 @@ void MainWindow::showNotification(INotificationDelegate* del)
|
||||
|
||||
void MainWindow::showHomeOnOpen()
|
||||
{
|
||||
// Don't open Home tab
|
||||
if (!Preferences::instance().general.showHome()) {
|
||||
configureWorkspaceLayout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getHomeView()->parent()) {
|
||||
TabView* selectedTab = m_tabsBar->getSelectedTab();
|
||||
|
||||
|
@ -1050,17 +1050,15 @@ void SkinTheme::paintLinkLabel(PaintEvent& ev)
|
||||
if (styleProp)
|
||||
style = styleProp->getStyle();
|
||||
|
||||
if (!is_transparent(bg))
|
||||
g->fillRect(bg, rc);
|
||||
rc.shrink(widget->border());
|
||||
|
||||
Style::State state;
|
||||
if (widget->hasMouseOver()) state += Style::hover();
|
||||
if (widget->isSelected()) state += Style::clicked();
|
||||
if (!widget->isEnabled()) state += Style::disabled();
|
||||
|
||||
widget->getTextIconInfo(nullptr, &text);
|
||||
style->paint(g, text, widget->text().c_str(), state);
|
||||
if (!is_transparent(bg))
|
||||
g->fillRect(bg, rc);
|
||||
|
||||
style->paint(g, rc, widget->text().c_str(), state);
|
||||
}
|
||||
|
||||
void SkinTheme::paintListBox(PaintEvent& ev)
|
||||
|
@ -31,7 +31,8 @@ using namespace gfx;
|
||||
using namespace ui;
|
||||
|
||||
ZoomEntry::ZoomEntry()
|
||||
: IntEntry(0, render::Zoom::linearValues()-1, this)
|
||||
: IntEntry(
|
||||
0, render::Zoom::fromLinearScale(render::Zoom::linearValues()-1).scale()*100, this)
|
||||
, m_locked(false)
|
||||
{
|
||||
setSuffix("%");
|
||||
|
@ -29,7 +29,7 @@ namespace ui {
|
||||
using namespace gfx;
|
||||
|
||||
IntEntry::IntEntry(int min, int max, SliderDelegate* sliderDelegate)
|
||||
: Entry(int(std::ceil(std::log10((double)max)))+1, "")
|
||||
: Entry(int(std::floor(std::log10(double(max))))+1, "")
|
||||
, m_min(min)
|
||||
, m_max(max)
|
||||
, m_slider(m_min, m_max, m_min, sliderDelegate)
|
||||
|
@ -1671,7 +1671,8 @@ static Widget* next_widget(Widget* widget)
|
||||
if (!widget->children().empty())
|
||||
return UI_FIRST_WIDGET(widget->children());
|
||||
|
||||
while (widget->parent()->type() != kManagerWidget) {
|
||||
while (widget->parent() &&
|
||||
widget->parent()->type() != kManagerWidget) {
|
||||
WidgetsList::const_iterator begin = widget->parent()->children().begin();
|
||||
WidgetsList::const_iterator end = widget->parent()->children().end();
|
||||
WidgetsList::const_iterator it = std::find(begin, end, widget);
|
||||
|
@ -64,8 +64,7 @@ private:
|
||||
};
|
||||
|
||||
// Data for the main jmenubar or the first popuped-jmenubox
|
||||
struct MenuBaseData
|
||||
{
|
||||
struct MenuBaseData {
|
||||
// True when the menu-items must be opened with the cursor movement
|
||||
bool was_clicked;
|
||||
|
||||
@ -79,8 +78,7 @@ struct MenuBaseData
|
||||
|
||||
bool close_all;
|
||||
|
||||
MenuBaseData()
|
||||
{
|
||||
MenuBaseData() {
|
||||
was_clicked = false;
|
||||
is_filtering = false;
|
||||
is_processing = false;
|
||||
@ -158,11 +156,7 @@ MenuBox::MenuBox(WidgetType type)
|
||||
|
||||
MenuBox::~MenuBox()
|
||||
{
|
||||
if (m_base && m_base->is_filtering) {
|
||||
m_base->is_filtering = false;
|
||||
Manager::getDefault()->removeMessageFilter(kMouseDownMessage, this);
|
||||
}
|
||||
|
||||
stopFilteringMouseDown();
|
||||
delete m_base;
|
||||
}
|
||||
|
||||
@ -219,7 +213,7 @@ Menu* MenuBox::getMenu()
|
||||
MenuBaseData* MenuBox::createBase()
|
||||
{
|
||||
delete m_base;
|
||||
m_base = new MenuBaseData();
|
||||
m_base = new MenuBaseData;
|
||||
return m_base;
|
||||
}
|
||||
|
||||
@ -269,18 +263,29 @@ bool MenuItem::hasSubmenu() const
|
||||
|
||||
void Menu::showPopup(const gfx::Point& pos)
|
||||
{
|
||||
// Generally, when we call showPopup() the menu shouldn't contain a
|
||||
// parent menu-box, because we're filtering kMouseDownMessage to
|
||||
// close the popup automatically when we click outside the menubox.
|
||||
// Anyway there is one specific case were a clicked widget might
|
||||
// call showPopup() when it's clicked the first time, and a second
|
||||
// click could generate a kDoubleClickMessage which is then
|
||||
// converted to kMouseDownMessage to finally call showPopup() again.
|
||||
// In this case, the menu is already in a menubox.
|
||||
if (parent()) {
|
||||
static_cast<MenuBox*>(parent())->cancelMenuLoop();
|
||||
return;
|
||||
}
|
||||
|
||||
// New window and new menu-box
|
||||
Window* window = new Window(Window::WithoutTitleBar);
|
||||
base::UniquePtr<Window> window(new Window(Window::WithoutTitleBar));
|
||||
MenuBox* menubox = new MenuBox();
|
||||
MenuBaseData* base = menubox->createBase();
|
||||
base->was_clicked = true;
|
||||
base->is_filtering = true;
|
||||
Manager::getDefault()->addMessageFilter(kMouseDownMessage, menubox);
|
||||
|
||||
window->setMoveable(false); // Can't move the window
|
||||
|
||||
// Set children
|
||||
menubox->setMenu(this);
|
||||
menubox->startFilteringMouseDown();
|
||||
window->addChild(menubox);
|
||||
|
||||
window->remapWindow();
|
||||
@ -301,10 +306,9 @@ void Menu::showPopup(const gfx::Point& pos)
|
||||
Manager::getDefault()->freeFocus();
|
||||
|
||||
// Fetch the "menu" so it isn't destroyed
|
||||
menubox->setMenu(NULL);
|
||||
menubox->setMenu(nullptr);
|
||||
menubox->stopFilteringMouseDown();
|
||||
|
||||
// Destroy the window
|
||||
delete window;
|
||||
}
|
||||
|
||||
void Menu::onPaint(PaintEvent& ev)
|
||||
@ -374,7 +378,10 @@ bool MenuBox::onProcessMessage(Message* msg)
|
||||
// Fall through
|
||||
|
||||
case kMouseDownMessage:
|
||||
case kDoubleClickMessage:
|
||||
if (menu) {
|
||||
ASSERT(menu->parent() == this);
|
||||
|
||||
if (get_base(this)->is_processing)
|
||||
break;
|
||||
|
||||
@ -650,7 +657,7 @@ bool MenuBox::onProcessMessage(Message* msg)
|
||||
|
||||
default:
|
||||
if (msg->type() == kClosePopupMessage) {
|
||||
manager()->_closeWindow(window(), true);
|
||||
window()->closeWindow(nullptr);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -829,9 +836,9 @@ bool MenuItem::onProcessMessage(Message* msg)
|
||||
else
|
||||
manager()->setFocus(this->parent()->parent());
|
||||
|
||||
// It is not necessary to delete this window because it's
|
||||
// automatically destroyed by the manager
|
||||
// ... delete window;
|
||||
// Do not call "delete window" here, because it
|
||||
// (CustomizedWindowForMenuBox) will be deferDelete()d on
|
||||
// kCloseMessage.
|
||||
|
||||
if (last_of_close_chain) {
|
||||
base->close_all = false;
|
||||
@ -928,7 +935,11 @@ static MenuBox* get_base_menubox(Widget* widget)
|
||||
static MenuBaseData* get_base(Widget* widget)
|
||||
{
|
||||
MenuBox* menubox = get_base_menubox(widget);
|
||||
return menubox->getBase();
|
||||
ASSERT(menubox);
|
||||
if (menubox)
|
||||
return menubox->getBase();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MenuItem* Menu::getHighlightedItem()
|
||||
@ -1048,10 +1059,9 @@ void MenuItem::openSubmenu(bool select_first)
|
||||
// clicks outside the menu (and close all the hierarchy in that
|
||||
// case); the widget to intercept messages is the base menu-bar or
|
||||
// popuped menu-box
|
||||
if (!base->is_filtering) {
|
||||
base->is_filtering = true;
|
||||
Manager::getDefault()->addMessageFilter(kMouseDownMessage, get_base_menubox(this));
|
||||
}
|
||||
MenuBox* base_menubox = get_base_menubox(this);
|
||||
if (base_menubox)
|
||||
base_menubox->startFilteringMouseDown();
|
||||
}
|
||||
|
||||
void MenuItem::closeSubmenu(bool last_of_close_chain)
|
||||
@ -1128,10 +1138,7 @@ void Menu::closeAll()
|
||||
|
||||
base->close_all = true;
|
||||
base->was_clicked = false;
|
||||
if (base->is_filtering) {
|
||||
base->is_filtering = false;
|
||||
Manager::getDefault()->removeMessageFilter(kMouseDownMessage, base_menubox);
|
||||
}
|
||||
base_menubox->stopFilteringMouseDown();
|
||||
|
||||
menu->unhighlightItem();
|
||||
|
||||
@ -1162,6 +1169,24 @@ void MenuBox::closePopup()
|
||||
Manager::getDefault()->enqueueMessage(msg);
|
||||
}
|
||||
|
||||
void MenuBox::startFilteringMouseDown()
|
||||
{
|
||||
if (m_base && !m_base->is_filtering) {
|
||||
m_base->is_filtering = true;
|
||||
Manager::getDefault()->addMessageFilter(kMouseDownMessage, this);
|
||||
Manager::getDefault()->addMessageFilter(kDoubleClickMessage, this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBox::stopFilteringMouseDown()
|
||||
{
|
||||
if (m_base && m_base->is_filtering) {
|
||||
m_base->is_filtering = false;
|
||||
Manager::getDefault()->removeMessageFilter(kMouseDownMessage, this);
|
||||
Manager::getDefault()->removeMessageFilter(kDoubleClickMessage, this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBox::cancelMenuLoop()
|
||||
{
|
||||
Menu* menu = getMenu();
|
||||
|
@ -78,10 +78,13 @@ namespace ui {
|
||||
|
||||
private:
|
||||
void closePopup();
|
||||
void startFilteringMouseDown();
|
||||
void stopFilteringMouseDown();
|
||||
|
||||
MenuBaseData* m_base;
|
||||
|
||||
friend class Menu;
|
||||
friend class MenuItem;
|
||||
};
|
||||
|
||||
class MenuBar : public MenuBox {
|
||||
|
Loading…
x
Reference in New Issue
Block a user