Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add copy and paste commands to live layout editing #121

Merged
merged 9 commits into from
Jun 8, 2018
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