Skip to content

Commit

Permalink
Merge pull request #121 from reupen/live-editing-copy-and-paste
Browse files Browse the repository at this point in the history
Add copy and paste commands to live layout editing
  • Loading branch information
reupen authored Jun 8, 2018
2 parents a56ea70 + cc88047 commit b6c9ea9
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 187 deletions.
109 changes: 73 additions & 36 deletions foo_ui_columns/layout.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "stdafx.h"
#include "layout.h"
#include "splitter.h"
#include "splitter_utils.h"
#include "main_window.h"

// {755971A7-109B-41dc-BED9-5A05CC07C905}
static const GUID g_guid_layout = {0x755971a7, 0x109b, 0x41dc, {0xbe, 0xd9, 0x5a, 0x5, 0xcc, 0x7, 0xc9, 0x5}};
Expand Down Expand Up @@ -598,7 +600,7 @@ void layout_window::run_live_edit_base(const live_edit_data_t& p_data)

uie::window_info_list_simple panels;
g_get_panels_info(supported_panels, panels);
enum { ID_CLOSE = 1, ID_SHOW_CAPTION, ID_LOCKED, ID_CHANGE_BASE };
enum { ID_REMOVE = 1, ID_SHOW_CAPTION, ID_LOCKED, ID_COPY, ID_PASTE_ADD, ID_PARENT_PASTE_INSERT, ID_CHANGE_BASE };

pfc::string8 temp;
p_window->get_name(temp);
Expand All @@ -611,54 +613,75 @@ void layout_window::run_live_edit_base(const live_edit_data_t& p_data)
const UINT_PTR ID_CHANGE_SPLITTER_BASE = ID_CHANGE_BASE_SPLITTER_BASE + panels.get_count();
const UINT_PTR ID_ADD_BASE = ID_CHANGE_SPLITTER_BASE + panels.get_count();

if (hierarchy_count == 1) {
{
HMENU menu_change = CreatePopupMenu();
g_append_menu_panels(menu_change, panels, ID_CHANGE_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change, L"Change panel");
t_size index = pfc_infinite;
const auto found_in_parent
= p_container.is_valid() && p_container->find_by_ptr(p_data.m_hierarchy[hierarchy_count - 1], index);
const auto splitter_item_in_clipboard = cui::splitter_utils::is_splitter_item_in_clipboard();
const auto can_add_panel
= p_splitter.is_valid() && p_splitter->get_panel_count() < p_splitter->get_maximum_panel_count();
uie::splitter_item_ptr splitter_item;

if (found_in_parent) {
p_container->get_panel(index, splitter_item);

if (!p_splitter.is_valid()) {
const auto show_caption = cui::splitter_utils::get_config_item<bool>(
p_container, index, uie::splitter_window::bool_show_caption);

if (show_caption)
AppendMenu(
menu, MF_STRING | (show_caption.value() ? MF_CHECKED : NULL), ID_SHOW_CAPTION, L"Show caption");
}

const auto is_locked
= cui::splitter_utils::get_config_item<bool>(p_container, index, uie::splitter_window::bool_locked);

if (is_locked)
AppendMenu(menu, MF_STRING | (is_locked.value() ? MF_CHECKED : NULL), ID_LOCKED, L"Locked");
}

if (hierarchy_count == 1) {
HMENU menu_change_panel = CreatePopupMenu();
g_append_menu_panels(menu_change_panel, panels, ID_CHANGE_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change_panel, L"Change panel");

if (p_splitter.is_valid()) {
HMENU menu_change = CreatePopupMenu();
g_append_menu_splitters(menu_change, panels, ID_CHANGE_BASE_SPLITTER_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change, L"Change splitter");
HMENU menu_change_splitter = CreatePopupMenu();
g_append_menu_splitters(menu_change_splitter, panels, ID_CHANGE_BASE_SPLITTER_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change_splitter, L"Change splitter");
}
}

if (p_splitter.is_valid()) {
if (p_splitter->get_panel_count() < p_splitter->get_maximum_panel_count()) {
HMENU menu_add = CreatePopupMenu();
g_append_menu_panels(menu_add, panels, ID_ADD_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_add, L"Add panel");
}
if (p_container.is_valid()) {
HMENU menu_change = CreatePopupMenu();
g_append_menu_splitters(menu_change, panels, ID_CHANGE_SPLITTER_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change, L"Change splitter");
}
if (can_add_panel) {
HMENU menu_add = CreatePopupMenu();
g_append_menu_panels(menu_add, panels, ID_ADD_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_add, L"Add panel");
}
}

if (found_in_parent) {
AppendMenu(menu, MF_STRING, ID_COPY, L"Copy");
if (splitter_item_in_clipboard && can_add_panel)
AppendMenu(menu, MF_STRING, ID_PASTE_ADD, L"Paste (add)");
AppendMenu(menu, MF_STRING, ID_REMOVE, L"Remove");
}
t_size index = pfc_infinite;

if (p_container.is_valid()) {
if (p_container->find_by_ptr(p_data.m_hierarchy[hierarchy_count - 1], index)) {
if (p_container->get_config_item_supported(index, uie::splitter_window::bool_show_caption)) {
bool b_val;
p_container->get_config_item(index, uie::splitter_window::bool_show_caption, b_val);
AppendMenu(menu, MF_STRING | (b_val ? MF_CHECKED : NULL), ID_SHOW_CAPTION, L"Show caption");
}
if (p_container->get_config_item_supported(index, uie::splitter_window::bool_locked)) {
bool b_val;
p_container->get_config_item(index, uie::splitter_window::bool_locked, b_val);
AppendMenu(menu, MF_STRING | (b_val ? MF_CHECKED : NULL), ID_LOCKED, L"Locked");
}
AppendMenu(menu, MF_STRING, ID_CLOSE, L"Close");
}
uAppendMenu(menu, MF_MENUBREAK, (UINT_PTR)0, nullptr);
uAppendMenu(menu, MF_SEPARATOR, (UINT_PTR)0, nullptr);
p_container->get_name(temp);
uAppendMenu(menu, MF_STRING | MF_GRAYED, (UINT_PTR)0, temp);
if (p_container->get_panel_count() < p_container->get_maximum_panel_count()) {
HMENU menu_add = CreatePopupMenu();
g_append_menu_panels(menu_add, panels, ID_PARENT_ADD_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_add, L"Add panel");
if (found_in_parent && splitter_item_in_clipboard)
AppendMenu(menu, MF_STRING, ID_PARENT_PASTE_INSERT, L"Paste (insert)");
}
}

Expand All @@ -668,16 +691,30 @@ void layout_window::run_live_edit_base(const live_edit_data_t& p_data)
DestroyMenu(menu);

abort_callback_dummy p_abort;
if (cmd == ID_CLOSE) {
if (cmd == ID_REMOVE) {
p_container->remove_panel(p_window);
} else if (cmd == ID_SHOW_CAPTION) {
bool b_old;
p_container->get_config_item(index, uie::splitter_window::bool_show_caption, b_old);
p_container->set_config_item_t(index, uie::splitter_window::bool_show_caption, !b_old, p_abort);
auto old_value
= cui::splitter_utils::get_config_item<bool>(p_container, index, uie::splitter_window::bool_show_caption);
if (old_value)
p_container->set_config_item_t(index, uie::splitter_window::bool_show_caption, !old_value.value(), p_abort);
} else if (cmd == ID_LOCKED) {
bool b_old;
p_container->get_config_item(index, uie::splitter_window::bool_locked, b_old);
p_container->set_config_item_t(index, uie::splitter_window::bool_locked, !b_old, p_abort);
auto old_value
= cui::splitter_utils::get_config_item<bool>(p_container, index, uie::splitter_window::bool_locked);
if (old_value)
p_container->set_config_item_t(index, uie::splitter_window::bool_locked, !old_value.value(), p_abort);
} else if (cmd == ID_COPY) {
cui::splitter_utils::copy_splitter_item_to_clipboard_safe(cui::main_window.get_wnd(), splitter_item.get_ptr());
} else if (cmd == ID_PASTE_ADD) {
auto clipboard_splitter_item
= cui::splitter_utils::get_splitter_item_from_clipboard_safe(cui::main_window.get_wnd());
if (clipboard_splitter_item)
p_splitter->add_panel(clipboard_splitter_item.get());
} else if (cmd == ID_PARENT_PASTE_INSERT) {
auto clipboard_splitter_item
= cui::splitter_utils::get_splitter_item_from_clipboard_safe(cui::main_window.get_wnd());
if (clipboard_splitter_item)
p_container->insert_panel(index + 1, clipboard_splitter_item.get());
} else if (cmd >= ID_CHANGE_BASE && cmd < panels.get_count() + ID_CHANGE_BASE) {
t_size panel_index = cmd - ID_CHANGE_BASE;
uie::splitter_item_ptr si = new uie::splitter_item_simple_t;
Expand Down
134 changes: 0 additions & 134 deletions foo_ui_columns/splitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,140 +50,6 @@ void g_append_menu_splitters(HMENU menu, const uie::window_info_list_simple& pan
}
}

/// don't pass smartptrs by reference as they may be nuked when destroying stuff
void g_run_live_edit_contextmenu(HWND wnd, POINT pt_menu, uih::TranslucentFillWindow& p_overlay, const RECT& rc_overlay,
uie::window_ptr ptr, uie::splitter_window_ptr p_container, t_size index, uie::window_host_ptr& p_host)
{
// console::print("g_run_live_edit_contextmenu");
// if (!m_trans_fill.get_wnd())
{
HWND wnd_over = p_overlay.create(wnd, uih::WindowPosition(rc_overlay));
HWND wnd_root = (GetAncestor(wnd, GA_ROOT));
// HWND wnd_next = GetWindow(wnd_root, GW_HWNDNEXT);
WindowEnum_t WindowEnum(wnd_root);
WindowEnum.run();
// console::formatter() << WindowEnum.m_wnd_list.get_count() << pfc::format_hex((t_size)wnd_root, 8) << " " <<
// pfc::format_hex((t_size)wnd_next, 8); SetWindowPos(wnd_over, GetWindow(GetAncestor(wnd, GA_ROOT),
// GW_HWNDNEXT), 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
t_size count_owned = WindowEnum.m_wnd_list.get_count();
if (count_owned) {
// console::formatter() << count_owned << " " <<
// pfc::format_hex((t_uint32)WindowEnum.m_wnd_list[count_owned-1]) << " " <<
// string_utf8_from_window(WindowEnum.m_wnd_list[count_owned-1]);
SetWindowPos(wnd_over, WindowEnum.m_wnd_list[count_owned - 1], 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
}
ShowWindow(wnd_over, SW_SHOWNOACTIVATE);

HMENU menu = CreatePopupMenu();
HMENU menu_change = CreatePopupMenu();
uie::window_info_list_simple panels;
g_get_panel_list(panels, p_host);
enum { ID_CLOSE = 1, ID_CHANGE_BASE = 2 };

uie::splitter_window_ptr p_splitter;
if (ptr.is_valid())
ptr->service_query_t(p_splitter);

g_append_menu_panels(menu_change, panels, ID_CHANGE_BASE);
pfc::string8 temp;
if (ptr.is_valid())
ptr->get_name(temp);
uAppendMenu(menu, MF_STRING | MF_GRAYED, (UINT_PTR)0, temp);
// uAppendMenu(menu, MF_MENUBREAK, (UINT_PTR)0, NULL);

const UINT_PTR ID_ADD_BASE = ID_CHANGE_BASE + panels.get_count();
const UINT_PTR ID_CHANGE_SPLITTER_BASE = ID_ADD_BASE + panels.get_count();
const UINT_PTR ID_PARENT_ADD_BASE = ID_CHANGE_SPLITTER_BASE + panels.get_count();
if (p_splitter.is_valid()) {
if (p_splitter->get_panel_count() < p_splitter->get_maximum_panel_count()) {
HMENU menu_add = CreatePopupMenu();
g_append_menu_panels(menu_add, panels, ID_ADD_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_add, L"Add panel");
}
HMENU menu_change = CreatePopupMenu();
g_append_menu_splitters(menu_change, panels, ID_CHANGE_SPLITTER_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change, L"Change splitter");
}

AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_change, L"Change panel");
AppendMenu(menu, MF_STRING, ID_CLOSE, L"Close");

if (p_container->get_panel_count() < p_container->get_maximum_panel_count()) {
uAppendMenu(menu, MF_MENUBREAK, (UINT_PTR)0, nullptr);
p_container->get_name(temp);
uAppendMenu(menu, MF_STRING | MF_GRAYED, (UINT_PTR)0, temp);

HMENU menu_add = CreatePopupMenu();
g_append_menu_panels(menu_add, panels, ID_PARENT_ADD_BASE);
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT_PTR)menu_add, L"Add panel");
}
auto cmd = (unsigned)TrackPopupMenu(
menu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, pt_menu.x, pt_menu.y, 0, wnd, nullptr);
p_overlay.destroy();
{
{
if (cmd) {
if (cmd == ID_CLOSE) {
p_container->remove_panel(index);
} else if (cmd >= ID_CHANGE_BASE && cmd < panels.get_count() + ID_CHANGE_BASE) {
t_size panel_index = cmd - ID_CHANGE_BASE;
uie::splitter_item_ptr si = new uie::splitter_item_simple_t;
si->set_panel_guid(panels[panel_index].guid);
p_container->replace_panel(index, si.get_ptr());
} else if (cmd >= ID_ADD_BASE && cmd < panels.get_count() + ID_ADD_BASE) {
t_size panel_index = cmd - ID_ADD_BASE;
uie::splitter_item_ptr si = new uie::splitter_item_simple_t;
si->set_panel_guid(panels[panel_index].guid);
p_splitter->add_panel(si.get_ptr());
} else if (cmd >= ID_CHANGE_SPLITTER_BASE && cmd < panels.get_count() + ID_CHANGE_SPLITTER_BASE) {
t_size panel_index = cmd - ID_CHANGE_SPLITTER_BASE;

uie::window_ptr window;
service_ptr_t<uie::splitter_window> splitter;
if (uie::window::create_by_guid(panels[panel_index].guid, window)
&& window->service_query_t(splitter)) {
unsigned count = min(p_splitter->get_panel_count(), splitter->get_maximum_panel_count());
if (count == p_splitter->get_panel_count()
|| MessageBox(wnd,
_T("The number of child items will not fit in the selected splitter type. ")
_T("Continue?"),
_T("Warning"), MB_YESNO | MB_ICONEXCLAMATION)
== IDYES) {
for (unsigned n = 0; n < count; n++) {
uie::splitter_item_ptr ptr;
p_splitter->get_panel(n, ptr);
splitter->add_panel(ptr.get_ptr());
}
uie::splitter_item_ptr newsi;
p_container->get_panel(index, newsi);

stream_writer_memblock conf;
abort_callback_dummy p_abort;
try {
splitter->get_config(&conf, p_abort);
} catch (const pfc::exception&) {
}
newsi->set_panel_guid(panels[panel_index].guid);
newsi->set_panel_config_from_ptr(conf.m_data.get_ptr(), conf.m_data.get_size());

p_container->replace_panel(index, newsi.get_ptr());
}
}

} else if (cmd >= ID_PARENT_ADD_BASE && cmd < panels.get_count() + ID_PARENT_ADD_BASE) {
t_size panel_index = cmd - ID_PARENT_ADD_BASE;
uie::splitter_item_ptr si = new uie::splitter_item_simple_t;
si->set_panel_guid(panels[panel_index].guid);
p_container->add_panel(si.get_ptr());
}
}
}
}
DestroyMenu(menu);
}
}

void clip_minmaxinfo(MINMAXINFO& mmi)
{
mmi.ptMinTrackSize.x = min(mmi.ptMinTrackSize.x, MAXSHORT);
Expand Down
2 changes: 0 additions & 2 deletions foo_ui_columns/splitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,6 @@ class WindowEnum_t {
void g_get_panel_list(uie::window_info_list_simple& p_out, uie::window_host_ptr& p_host);
void g_append_menu_panels(HMENU menu, const uie::window_info_list_simple& panels, UINT base);
void g_append_menu_splitters(HMENU menu, const uie::window_info_list_simple& panels, UINT base);
void g_run_live_edit_contextmenu(HWND wnd, POINT pt_menu, uih::TranslucentFillWindow& p_overlay, const RECT& rc_overlay,
uie::window_ptr ptr, uie::splitter_window_ptr p_container, t_size index, uie::window_host_ptr& p_host);
void clip_minmaxinfo(MINMAXINFO& mmi);

#endif
10 changes: 10 additions & 0 deletions foo_ui_columns/splitter_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,14 @@ std::unique_ptr<uie::splitter_item_full_v3_impl_t> get_splitter_item_from_clipbo
return deserialise_splitter_item({data.get_ptr(), gsl::narrow<gsl::span<t_uint8>::index_type>(data.get_size())});
}

std::unique_ptr<uie::splitter_item_full_v3_impl_t> get_splitter_item_from_clipboard_safe(HWND wnd)
{
try {
return get_splitter_item_from_clipboard();
} catch (const exception_io& ex) {
uMessageBox(wnd, ex.what(), u8"Error – Paste Panel", MB_OK | MB_ICONERROR);
}
return {};
}

} // namespace cui::splitter_utils
23 changes: 22 additions & 1 deletion foo_ui_columns/splitter_utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <optional>

namespace cui::splitter_utils {

pfc::array_t<t_uint8> serialise_splitter_item(const uie::splitter_item_full_v3_impl_t* item);
Expand All @@ -18,7 +20,26 @@ void copy_splitter_item_to_clipboard(const SplitterItem* item)
}
}

template <typename SplitterItem>
void copy_splitter_item_to_clipboard_safe(HWND wnd, const SplitterItem* item)
{
try {
copy_splitter_item_to_clipboard(item);
} catch (const exception_io& ex) {
uMessageBox(wnd, ex.what(), u8"Error – Copy Panel", MB_OK | MB_ICONERROR);
}
}

bool is_splitter_item_in_clipboard();
std::unique_ptr<uie::splitter_item_full_v3_impl_t> get_splitter_item_from_clipboard();
std::unique_ptr<uie::splitter_item_full_v3_impl_t> get_splitter_item_from_clipboard_safe(HWND wnd);

template <class T>
std::optional<T> get_config_item(uie::splitter_window::ptr splitter, size_t index, GUID item)
{
T value;
if (splitter->get_config_item(index, item, value))
return {value};
return {};
}

} // namespace cui::splitter_utils
17 changes: 3 additions & 14 deletions foo_ui_columns/tab_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,7 @@ void LayoutTab::copy_item(HWND wnd, HTREEITEM ti)

if (TreeView_GetItem(wnd_tv, &item)) {
LayoutTabNode::ptr p_node = reinterpret_cast<LayoutTabNode*>(item.lParam);
try {
splitter_utils::copy_splitter_item_to_clipboard(p_node->m_item->get_ptr());
} catch (const exception_io& ex) {
uMessageBox(wnd, ex.what(), u8"Error – Copy Panel", MB_OK | MB_ICONERROR);
}
splitter_utils::copy_splitter_item_to_clipboard_safe(wnd, p_node->m_item->get_ptr());
}
}

Expand Down Expand Up @@ -293,16 +289,9 @@ void LayoutTab::paste_item(HWND wnd, HTREEITEM ti_parent, HTREEITEM ti_after)
if (!TreeView_GetItem(wnd_tv, &item))
return;

std::unique_ptr<uie::splitter_item_full_v3_impl_t> splitter_item;

try {
splitter_item = splitter_utils::get_splitter_item_from_clipboard();
} catch (const exception_io& ex) {
uMessageBox(wnd, ex.what(), u8"Error – Paste Panel", MB_OK | MB_ICONERROR);
return;
}
auto splitter_item = splitter_utils::get_splitter_item_from_clipboard_safe(wnd);

if (!fix_paste_item(*splitter_item))
if (!splitter_item || !fix_paste_item(*splitter_item))
return;

*p_node->m_item = splitter_item.release();
Expand Down

0 comments on commit b6c9ea9

Please sign in to comment.