mirror of https://github.com/aseprite/aseprite.git
189 lines
4.6 KiB
C++
189 lines
4.6 KiB
C++
|
// Aseprite
|
||
|
// Copyright (c) 2024 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/font_entry.h"
|
||
|
|
||
|
#include "app/console.h"
|
||
|
#include "app/ui/font_popup.h"
|
||
|
#include "fmt/format.h"
|
||
|
#include "ui/display.h"
|
||
|
#include "ui/manager.h"
|
||
|
#include "ui/message.h"
|
||
|
|
||
|
#include <cstdlib>
|
||
|
|
||
|
namespace app {
|
||
|
|
||
|
using namespace ui;
|
||
|
|
||
|
FontEntry::FontFace::FontFace()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool FontEntry::FontFace::onProcessMessage(Message* msg)
|
||
|
{
|
||
|
switch (msg->type()) {
|
||
|
|
||
|
// If we press the mouse button in the FontFace widget, and drag
|
||
|
// the mouse (without releasing the mouse button) to the popup, we
|
||
|
// send the mouse message to the popup.
|
||
|
case kMouseMoveMessage:
|
||
|
if (hasCapture() && m_popup) {
|
||
|
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||
|
const gfx::Point screenPos =
|
||
|
mouseMsg->display()->nativeWindow()->pointToScreen(mouseMsg->position());
|
||
|
Widget* pick = manager()->pickFromScreenPos(screenPos);
|
||
|
Widget* target = m_popup->getListBox();
|
||
|
|
||
|
if (pick && (pick == target ||
|
||
|
pick->hasAncestor(target))) {
|
||
|
releaseMouse();
|
||
|
|
||
|
MouseMessage mouseMsg2(
|
||
|
kMouseDownMessage,
|
||
|
*mouseMsg,
|
||
|
mouseMsg->positionForDisplay(pick->display()));
|
||
|
mouseMsg2.setRecipient(pick);
|
||
|
mouseMsg2.setDisplay(pick->display());
|
||
|
pick->sendMessage(&mouseMsg2);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case kMouseDownMessage:
|
||
|
case kFocusEnterMessage:
|
||
|
if (!m_popup) {
|
||
|
try {
|
||
|
const FontInfo info = static_cast<FontEntry*>(parent())->info();
|
||
|
|
||
|
m_popup.reset(new FontPopup(info));
|
||
|
m_popup->ChangeFont.connect([this](const FontInfo& fontInfo){
|
||
|
FontChange(fontInfo);
|
||
|
});
|
||
|
|
||
|
// If we press ESC in the popup we focus this FontFace field.
|
||
|
m_popup->EscKey.connect([this](){
|
||
|
requestFocus();
|
||
|
});
|
||
|
}
|
||
|
catch (const std::exception& ex) {
|
||
|
Console::showException(ex);
|
||
|
}
|
||
|
}
|
||
|
if (!m_popup->isVisible()) {
|
||
|
m_popup->showPopup(display(), bounds());
|
||
|
requestFocus();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case kFocusLeaveMessage: {
|
||
|
// If we lost focus by a widget that is not part of the popup,
|
||
|
// we close the popup.
|
||
|
auto* newFocus = static_cast<FocusMessage*>(msg)->newFocus();
|
||
|
if (m_popup &&
|
||
|
newFocus &&
|
||
|
newFocus->window() != m_popup.get()) {
|
||
|
m_popup->closeWindow(nullptr);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case kKeyDownMessage:
|
||
|
// If the popup is visible and we press the Down arrow key, we
|
||
|
// start navigating the popup list.
|
||
|
if (hasFocus() &&
|
||
|
m_popup &&
|
||
|
m_popup->isVisible()) {
|
||
|
const auto* keymsg = static_cast<const KeyMessage*>(msg);
|
||
|
switch (keymsg->scancode()) {
|
||
|
case kKeyDown:
|
||
|
m_popup->focusListBox();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
return SearchEntry::onProcessMessage(msg);
|
||
|
}
|
||
|
|
||
|
void FontEntry::FontFace::onChange()
|
||
|
{
|
||
|
SearchEntry::onChange();
|
||
|
|
||
|
m_popup->setSearchText(text());
|
||
|
}
|
||
|
|
||
|
FontEntry::FontSize::FontSize()
|
||
|
{
|
||
|
setEditable(true);
|
||
|
for (int i : { 8, 9, 10, 11, 12, 14, 16, 18, 22, 24, 26, 28, 36, 48, 72 })
|
||
|
addItem(fmt::format("{}", i));
|
||
|
}
|
||
|
|
||
|
void FontEntry::FontSize::onEntryChange()
|
||
|
{
|
||
|
ComboBox::onEntryChange();
|
||
|
Change();
|
||
|
}
|
||
|
|
||
|
FontEntry::FontEntry()
|
||
|
: m_antialias("Antialias")
|
||
|
{
|
||
|
m_face.setExpansive(true);
|
||
|
m_size.setExpansive(false);
|
||
|
m_antialias.setExpansive(false);
|
||
|
addChild(&m_face);
|
||
|
addChild(&m_size);
|
||
|
addChild(&m_antialias);
|
||
|
|
||
|
m_face.FontChange.connect([this](const FontInfo& newTypeName) {
|
||
|
setInfo(FontInfo(newTypeName,
|
||
|
m_info.size(),
|
||
|
m_info.antialias()),
|
||
|
From::Face);
|
||
|
invalidate();
|
||
|
});
|
||
|
|
||
|
m_size.Change.connect([this](){
|
||
|
const float newSize = std::strtof(m_size.getValue().c_str(), nullptr);
|
||
|
setInfo(FontInfo(m_info,
|
||
|
newSize,
|
||
|
m_info.antialias()),
|
||
|
From::Size);
|
||
|
});
|
||
|
|
||
|
m_antialias.Click.connect([this](){
|
||
|
setInfo(FontInfo(m_info,
|
||
|
m_info.size(),
|
||
|
m_antialias.isSelected()),
|
||
|
From::Antialias);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void FontEntry::setInfo(const FontInfo& info,
|
||
|
const From fromField)
|
||
|
{
|
||
|
m_info = info;
|
||
|
|
||
|
m_face.setText(info.title());
|
||
|
|
||
|
if (fromField != From::Size)
|
||
|
m_size.setValue(fmt::format("{}", info.size()));
|
||
|
|
||
|
if (fromField != From::Antialias)
|
||
|
m_antialias.setSelected(info.antialias());
|
||
|
|
||
|
FontChange(m_info);
|
||
|
}
|
||
|
|
||
|
} // namespace app
|