Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 5f76a77
Author: Wojciech Jarosz <[email protected]>
Date:   Mon Jan 23 10:06:09 2023 -0500

    closing #116

commit 59c5965
Author: Wojciech Jarosz <[email protected]>
Date:   Mon Jan 23 10:03:07 2023 -0500

    typos

commit 94cc093
Author: Wojciech Jarosz <[email protected]>
Date:   Sun Jan 22 16:39:09 2023 -0500

    refactoring shortcuts

    * allowing multiple shortcuts
    * don't tonemap alpha channel
    * don't show eyedropper overlay if mouse is over panels
  • Loading branch information
wkjarosz committed Feb 10, 2023
1 parent 8164934 commit 00c6c7e
Show file tree
Hide file tree
Showing 11 changed files with 707 additions and 644 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ elseif(WIN32)
install(TARGETS hdrbatch RUNTIME DESTINATION "bin")
else()
install(TARGETS HDRView RUNTIME DESTINATION "bin")
install(TARGETS hdrbatch RUNTIME DESTINATION "bin")
install(FILES resources/hdrview.desktop DESTINATION "/usr/share/applications")
install(FILES resources/icon-512.png DESTINATION "/usr/share/icons/hicolor/1024x1024/apps" RENAME hdrview.png)
install(FILES resources/icon-512.png DESTINATION "/usr/share/icons/hicolor/512x512/apps" RENAME hdrview.png)
Expand Down
16 changes: 8 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- [ ] Allow skipping DNG demosaicing during load
- [ ] Add demosaicing/color correction/white balancing post-load filters
- [ ] Will require storing DNG metadata to apply correct color-correction matrix
- [ ] Selection support
- [x] Selection support
- [ ] More image filters/transformations/adjustments
- [x] Canvas size/cropping
- [ ] White balance adjustment
Expand All @@ -26,18 +26,18 @@
- [ ] Match color/histogram matching
- [ ] FFT-based convolution/blur
- [ ] Motion blur
- [ ] Merge down/flatten layers
- [x] Merge down/flatten layers
- [ ] Enable processing/filtering images passed on command-line even in GUI mode (e.g. load many images, blur them, and then display them in the GUI, possibly without saving)
- [ ] HDR merging
- [ ] HDR tonemapping
- [ ] General image editing
- [ ] Clone stamp
- [ ] Airbrush
- [ ] Cropping
- [x] General image editing
- [x] Clone stamp
- [x] Airbrush
- [x] Cropping
- [ ] GUI improvements
- [x] Add support for resizing side panel
- [ ] Allow error logging to output to a debug status panel in the GUI.
- [ ] Improved drop-down menus
- [ ] Save all
- [x] Improved drop-down menus
- [x] Save all
- [x] Close all
- [ ] Show command history and allow undoing/redoing multiple steps at once
5 changes: 3 additions & 2 deletions src/hdrimageview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ void HDRImageView::write_settings(json &settings) const

Color4 HDRImageView::tonemap(const Color4 &color) const
{
float gain = powf(2.0f, m_exposure);
return m_sRGB ? LinearToSRGB(color * gain) : pow(color * gain, Color4(1.0 / m_gamma));
float gain = powf(2.0f, m_exposure);
Color4 exposed{Color3(color) * gain, color.a};
return m_sRGB ? LinearToSRGB(exposed) : pow(exposed, Color4(1.0 / m_gamma));
}

void HDRImageView::set_current_image(XPUImagePtr cur)
Expand Down
1,114 changes: 567 additions & 547 deletions src/hdrviewscreen.cpp

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions src/hdrviewscreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,16 @@ class HDRViewScreen : public Screen
void update_caption();

private:
void draw_widgets();
void bring_to_focus() const;
void show_help_window();
void update_layout();
bool at_side_panel_edge(const Vector2i &p);
bool at_tool_panel_edge(const Vector2i &p);
void resize_side_panel(int w);
void resize_tool_panel(int w);
Dialog *active_dialog() const;

void create_menubar();
void draw_widgets();
void bring_to_focus() const;
void show_help_window();
void update_layout();
bool at_side_panel_edge(const Vector2i &p);
bool at_tool_panel_edge(const Vector2i &p);
void resize_side_panel(int w);
void resize_tool_panel(int w);
Dialog *active_dialog() const;
nlohmann::json &recent_files();

Window *m_top_panel, *m_side_panel, *m_tool_panel, *m_status_bar;
Expand Down Expand Up @@ -125,6 +125,8 @@ class HDRViewScreen : public Screen
bool m_dragging_tool_panel = false;
bool m_need_layout_update = true;
bool m_solo_mode = false;
bool m_capability_EDR = false;
bool m_capability_10bit = false;

std::thread m_gui_refresh_thread;
std::atomic<int> m_gui_refresh = 0;
Expand Down
10 changes: 5 additions & 5 deletions src/imagelistpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,9 @@ ImageListPanel::ImageListPanel(Widget *parent, HDRViewScreen *screen, HDRImageVi
agl->set_anchor(new Label(grid, "Mode:", "sans", 14),
AdvancedGridLayout::Anchor(0, agl->row_count() - 1, Alignment::Fill, Alignment::Fill));

auto add_item = [](Dropdown *btn, const std::string &name, int index, int modifier = 0, int button = 0)
auto add_item = [](Dropdown *btn, const std::string &name, int index, const vector<MenuItem::Shortcut> &s)
{
auto i = btn->popup()->add<MenuItem>(name);
i->set_shortcut(modifier, button);
auto i = new MenuItem(btn->popup(), name, 0, s);
i->set_flags(Button::RadioButton);
i->set_callback(
[index, btn]
Expand All @@ -94,7 +93,7 @@ ImageListPanel::ImageListPanel(Widget *parent, HDRViewScreen *screen, HDRImageVi

m_blend_modes = new Dropdown(grid);
for (int i = 0; i < (int)blend_mode_names().size(); ++i)
add_item(m_blend_modes, blend_mode_names()[i], i, GLFW_MOD_SHIFT, GLFW_KEY_1 + i);
add_item(m_blend_modes, blend_mode_names()[i], i, {{GLFW_MOD_SHIFT, GLFW_KEY_1 + i}});
m_blend_modes->set_selected_index(0);
m_blend_modes->set_fixed_height(19);
m_blend_modes->set_selected_callback([img_view](int b) { img_view->set_blend_mode(EBlendMode(b)); });
Expand All @@ -109,7 +108,8 @@ ImageListPanel::ImageListPanel(Widget *parent, HDRViewScreen *screen, HDRImageVi

m_channels = new Dropdown(grid);
for (int i = 0; i < (int)channel_names().size(); ++i)
add_item(m_channels, channel_names()[i], i, i <= 8 ? SYSTEM_COMMAND_MOD : 0, i <= 8 ? GLFW_KEY_0 + i : 0);
add_item(m_channels, channel_names()[i], i,
{{i <= 9 ? SYSTEM_COMMAND_MOD : 0, i <= 9 ? GLFW_KEY_0 + i : 0}});
m_channels->set_selected_index(0);
m_channels->set_fixed_height(19);
set_channel(EChannel::RGB);
Expand Down
122 changes: 71 additions & 51 deletions src/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ using std::vector;

NAMESPACE_BEGIN(nanogui)

MenuItem::MenuItem(Widget *parent, const std::string &caption, int button_icon, const Shortcut &s) :
Button(parent, caption, button_icon), m_shortcut(s)
MenuItem::MenuItem(Widget *parent, const std::string &caption, int button_icon, const std::vector<Shortcut> &s) :
Button(parent, caption, button_icon), m_shortcuts(s)
{
set_fixed_height(PopupMenu::menu_item_height);
m_icon_position = IconPosition::Left;
Expand All @@ -46,35 +46,46 @@ MenuItem::Shortcut::Shortcut(int m, int k) : modifiers(m), key(k)
if (32 < key && key < 128)
text += char(key);
// function keys
else if (key == GLFW_KEY_SPACE)
text += "Space";
else if (GLFW_KEY_F1 <= key && key <= GLFW_KEY_F25)
text += fmt::format("F{}", key - GLFW_KEY_F1 + 1);
else if (key == GLFW_KEY_BACKSPACE)
text += "Backspace";
else if (key == GLFW_KEY_DELETE)
text += "Delete";
else if (key == GLFW_KEY_UP)
text += "Up";
else if (key == GLFW_KEY_DOWN)
text += "Down";
else if (key == GLFW_KEY_LEFT)
text += "Left";
else if (key == GLFW_KEY_RIGHT)
text += "Right";
else if (key == GLFW_KEY_PAGE_UP)
text += "Page Up";
else if (key == GLFW_KEY_DOWN)
text += "Page Down";
else if (key == GLFW_KEY_TAB)
text += "Tab";
else if (key == GLFW_KEY_ESCAPE)
text += "Esc";
else if (key == GLFW_KEY_ENTER)
text += "Enter";
else if (GLFW_KEY_KP_0 <= key && key <= GLFW_KEY_KP_0)
text += fmt::format("{}", key - GLFW_KEY_KP_0);

static const std::map<int, string> key_map = {
{GLFW_KEY_SPACE, "Space"},
{GLFW_KEY_ESCAPE, "Esc"},
{GLFW_KEY_ENTER, "Enter"},
{GLFW_KEY_TAB, "Tab"},
{GLFW_KEY_BACKSPACE, "Backspace"},
{GLFW_KEY_INSERT, "Insert"},
{GLFW_KEY_DELETE, "Delete"},
{GLFW_KEY_RIGHT, "Right"},
{GLFW_KEY_LEFT, "Left"},
{GLFW_KEY_DOWN, "Down"},
{GLFW_KEY_UP, "Up"},
{GLFW_KEY_PAGE_UP, "Page Up"},
{GLFW_KEY_PAGE_DOWN, "Page Down"},
{GLFW_KEY_HOME, "Home"},
{GLFW_KEY_END, "End"},
{GLFW_KEY_CAPS_LOCK, "Caps lock"},
{GLFW_KEY_SCROLL_LOCK, "Scroll lock"},
{GLFW_KEY_NUM_LOCK, "Num lock"},
{GLFW_KEY_PRINT_SCREEN, "Print"},
{GLFW_KEY_PAUSE, "Pause"},
{GLFW_KEY_KP_DECIMAL, "."},
{GLFW_KEY_KP_DIVIDE, "/"},
{GLFW_KEY_KP_MULTIPLY, "*"},
{GLFW_KEY_KP_SUBTRACT, "-"},
{GLFW_KEY_KP_ADD, "+"},
{GLFW_KEY_KP_ENTER, "Enter"},
{GLFW_KEY_KP_EQUAL, "="},
};

if (auto search = key_map.find(key); search != key_map.end())
text += search->second;
}

void MenuItem::set_shortcut(int modifiers, int key) { m_shortcut = Shortcut(modifiers, key); }
void MenuItem::add_shortcut(const Shortcut &s) { m_shortcuts.push_back(s); }

Vector2i MenuItem::preferred_text_size(NVGcontext *ctx) const
{
Expand All @@ -96,7 +107,7 @@ Vector2i MenuItem::preferred_size(NVGcontext *ctx) const
// iw = nvgTextBounds(ctx, 0, 0, utf8(m_icon).data(), nullptr, nullptr) + m_size.y() * 0.15f;
float iw = font_size * icon_scale();
float sw =
m_shortcut.text.size() ? nvgTextBounds(ctx, 0, 0, m_shortcut.text.c_str(), nullptr, nullptr) + iw * 5 : 0;
shortcut().text.size() ? nvgTextBounds(ctx, 0, 0, shortcut().text.c_str(), nullptr, nullptr) + iw * 5 : 0;
return preferred_text_size(ctx) + Vector2i((int)(iw + sw), 0);
}

Expand Down Expand Up @@ -187,17 +198,17 @@ void MenuItem::draw(NVGcontext *ctx)
nvgFillColor(ctx, text_color);
nvgText(ctx, text_pos.x(), text_pos.y() + 1, m_caption.c_str(), nullptr);

if (!m_shortcut.text.size())
if (!shortcut().text.size())
return;

// float sw = nvgTextBounds(ctx, 0, 0, m_shortcut.text.c_str(), nullptr, nullptr);
// float sw = nvgTextBounds(ctx, 0, 0, shortcut().text.c_str(), nullptr, nullptr);
Vector2f hotkey_pos(m_pos.x() + m_size.x() - 8, center.y() - 1);

nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE);
nvgFillColor(ctx, m_theme->m_text_color_shadow);
nvgText(ctx, hotkey_pos.x(), hotkey_pos.y(), m_shortcut.text.c_str(), nullptr);
nvgText(ctx, hotkey_pos.x(), hotkey_pos.y(), shortcut().text.c_str(), nullptr);
nvgFillColor(ctx, m_theme->m_disabled_text_color);
nvgText(ctx, hotkey_pos.x(), hotkey_pos.y() + 1, m_shortcut.text.c_str(), nullptr);
nvgText(ctx, hotkey_pos.x(), hotkey_pos.y() + 1, shortcut().text.c_str(), nullptr);
}

Separator::Separator(Widget *parent) : MenuItem(parent, "")
Expand Down Expand Up @@ -600,36 +611,38 @@ bool MenuBar::mouse_motion_event(const Vector2i &p, const Vector2i &rel, int but
return Window::mouse_motion_event(p, rel, button, modifiers);
}

bool MenuBar::process_hotkeys(int modifiers, int key)
bool MenuBar::process_shortcuts(int modifiers, int key)
{
spdlog::trace("Processing hotkeys:");
MenuItem::Shortcut pressed{modifiers, key};
spdlog::trace("Checking for keyboard shortcut: \"{}\"", pressed.text);
for (auto c : children())
if (auto menu = dynamic_cast<Dropdown *>(c))
{
for (auto c2 : menu->popup()->children())
if (auto item = dynamic_cast<MenuItem *>(c2))
{
auto shortcut = item->shortcut();

if (item->enabled() && key == shortcut.key && modifiers == shortcut.modifiers)
{
spdlog::trace("Handling keyboard shortcut {}: {} > {}", shortcut.text, menu->caption(),
item->caption());
if (item->flags() & Button::NormalButton)
{
if (item->callback())
item->callback()();
}
else
if (!item->enabled())
continue;
for (size_t i = 0; i < item->num_shortcuts(); ++i)
if (pressed == item->shortcut(i))
{
if (item->change_callback())
spdlog::trace("Handling keyboard shortcut \"{}\" with menu item: {} > {}",
item->shortcut(i).text, menu->caption(), item->caption());
if (item->flags() & Button::NormalButton)
{
if (item->callback())
item->callback()();
}
else
{
item->set_pushed(!item->pushed());
item->change_callback()(item->pushed());
if (item->change_callback())
{
item->set_pushed(!item->pushed());
item->change_callback()(item->pushed());
}
}
return true;
}
return true;
}
}
}
return false;
Expand All @@ -646,8 +659,15 @@ void MenuBar::add_shortcuts(HelpWindow *w)
if (!sep->visible())
w->add_separator(menu->caption());
if (auto item = dynamic_cast<MenuItem *>(c2))
{
// document the keyboard shortcut only if it is not visible in the menu
if (item->shortcut().text.size() && !item->visible())
w->add_shortcut(menu->caption(), item->shortcut().text, item->caption());

// any additional shortcuts are not visible, so document them if they exist
for (size_t i = 1; i < item->num_shortcuts(); ++i)
w->add_shortcut(menu->caption(), item->shortcut(i).text, item->caption());
}
}
}
}
Expand Down
31 changes: 26 additions & 5 deletions src/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,28 @@

NAMESPACE_BEGIN(nanogui)

/**
A #MenuItem can have one or more keyboard #Shortcuts which can be used to run the callback associated with the item.
These callbacks are run by #MenuBar::process_shortcuts for all #MenuItems associated with a #MenuBar.
If an item has more than one shortcut, the first one is the default one that is shown on the drawn UI (for instance,
along the right side of a dropdown menu). Since each shortcut can only represent a single key (plus modifiers), it is
sometimes useful to associate multiple keyboard shortcuts with the same menu item (e.g. to allow zooming with the '+'
key on the number row of the keyboard, as well as the '+' on the number pad).
These additional shortcuts are not currently visible directly in the UI. In the future, the plan is to also allow the
drawn UI to display alternate shortcuts based on what modifiers are currently being pressed (e.g. show "Close" when
only the command key is pressed, but "Close all" when the shift key is also pressed).
*/
class MenuItem : public Button
{
public:
/**
Represents a key press optionally combined with one or more modifier keys.
A Shortcut also stores a human-readible #text string describing the key combination for use by UI elements.
*/
struct Shortcut
{
int modifiers, key; ///< The GLFW modifiers (shift, command, etc) and key used to execute this shortcut
Expand All @@ -31,17 +50,19 @@ class MenuItem : public Button
}
};

MenuItem(Widget *parent, const std::string &caption = "Untitled", int button_icon = 0, const Shortcut &s = {0, 0});
MenuItem(Widget *parent, const std::string &caption = "Untitled", int button_icon = 0,
const std::vector<Shortcut> &s = {{0, 0}});

const Shortcut &shortcut() const { return m_shortcut; }
void set_shortcut(int modifiers, int button);
size_t num_shortcuts() const { return m_shortcuts.size(); }
const Shortcut &shortcut(size_t i = 0) const { return m_shortcuts.at(i); }
void add_shortcut(const Shortcut &s);

virtual void draw(NVGcontext *ctx) override;
Vector2i preferred_text_size(NVGcontext *ctx) const;
virtual Vector2i preferred_size(NVGcontext *ctx) const override;

protected:
Shortcut m_shortcut;
std::vector<Shortcut> m_shortcuts;
};

class Separator : public MenuItem
Expand Down Expand Up @@ -140,7 +161,7 @@ class MenuBar : public Window

Dropdown *add_menu(const std::string &name);

bool process_hotkeys(int modifiers, int key);
bool process_shortcuts(int modifiers, int key);
void add_shortcuts(HelpWindow *w);

virtual bool mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
Expand Down
12 changes: 6 additions & 6 deletions src/multigraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ using std::vector;

namespace
{
const int hpad = 11;
const int text_pad = 4;
constexpr int hpad = 11;
constexpr int text_pad = 4;
} // namespace

NAMESPACE_BEGIN(nanogui)
Expand All @@ -39,10 +39,10 @@ Vector2i MultiGraph::preferred_size(NVGcontext *) const { return Vector2i(256, 7

Vector2f MultiGraph::graph_coordinate_at(const Vector2f &position) const
{
Vector2f topLeft(x_position(0), y_position(0));
Vector2f bottomRight(x_position(1), y_position(1));
Vector2f graphSize = bottomRight - topLeft;
return (position - topLeft) / (graphSize);
Vector2f top_left(x_position(0), y_position(0));
Vector2f bottom_right(x_position(1), y_position(1));
Vector2f graph_size = bottom_right - top_left;
return (position - top_left) / (graph_size);
}

void MultiGraph::set_xticks(const std::vector<float> &ticks, const vector<string> &labels)
Expand Down
Loading

0 comments on commit 00c6c7e

Please sign in to comment.