* add support for TableView::onActivate(TableViewCell) to Windows, macOS
** allows the new input/hotkey mapping panels to work on Windows, macOS
* polish BrowserDialog behavior
This commit is contained in:
byuu 2019-08-01 02:40:35 +09:00
parent a7b30b069c
commit bc7456246c
8 changed files with 80 additions and 28 deletions

View File

@ -31,7 +31,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "bsnes";
static const string Version = "108.2";
static const string Version = "108.3";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org";

View File

@ -1,9 +1,4 @@
#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_MACOS)
//TODO: hiro support for TableView::activate(TableViewCell) is required for > 1 binding
enum : uint { BindingLimit = 1 };
#else
enum : uint { BindingLimit = 4 };
#endif
struct InputMapping {
auto bind() -> void;

View File

@ -110,13 +110,15 @@
tableView->doChange();
}
-(IBAction) activate:(id)sender {
tableView->doActivate({});
}
-(IBAction) doubleAction:(id)sender {
if([content clickedRow] >= 0) {
[self activate:self];
int row = [content clickedRow];
if(row >= 0 && row < tableView->state.items.size()) {
int column = [content clickedColumn];
if(column >= 0 && column < tableView->state.columns.size()) {
auto item = tableView->state.items[row];
auto cell = item->cell(column);
tableView->doActivate(cell);
}
}
}
@ -127,9 +129,14 @@
-(void) keyDown:(NSEvent*)event {
auto character = [[event characters] characterAtIndex:0];
if(character == NSEnterCharacter || character == NSCarriageReturnCharacter) {
if([self selectedRow] >= 0) {
[[self delegate] activate:self];
return;
int row = [self selectedRow];
if(row >= 0 && row < tableView->state.items.size()) {
int column = max(0, [self selectedColumn]); //can be -1?
if(column >= 0 && column < tableView->state.columns.size()) {
auto item = tableView->state.items[row];
auto cell = item->cell(column);
tableView->doActivate(cell);
}
}
}

View File

@ -20,7 +20,6 @@
-(NSString*) tableView:(NSTableView*)table toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation;
-(void) tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
-(void) tableViewSelectionDidChange:(NSNotification*)notification;
-(IBAction) activate:(id)sender;
-(IBAction) doubleAction:(id)sender;
@end

View File

@ -8,6 +8,8 @@ struct BrowserDialogWindow {
auto activate() -> void;
auto change() -> void;
auto context() -> void;
auto isObject(const string& name) -> bool;
auto isFile(const string& name) -> bool;
auto isFolder(const string& name) -> bool;
auto isMatch(const string& name) -> bool;
auto run() -> BrowserDialog::Response;
@ -43,7 +45,7 @@ private:
vector<vector<string>> filters;
};
//accept button clicked, or enter pressed on file name line edit
//accept button clicked, or enter pressed inside file name field
//also called by table view activate after special case handling
auto BrowserDialogWindow::accept() -> void {
auto batched = view.batched();
@ -51,7 +53,7 @@ auto BrowserDialogWindow::accept() -> void {
if(state.action == "openFile" && batched.size() == 1) {
string name = batched[0].text();
if(isFolder(name)) return setPath({state.path, name});
response.selected.append(string{state.path, name});
response.selected.append({state.path, name});
}
if(state.action == "openFiles" && batched) {
@ -63,20 +65,20 @@ auto BrowserDialogWindow::accept() -> void {
response.selected.reset();
return;
}
response.selected.append(string{state.path, name});
response.selected.append({state.path, name});
}
}
if(state.action == "openFolder" && batched.size() == 1) {
string name = batched[0].text();
if(!isMatch(name)) return setPath({state.path, name});
response.selected.append(string{state.path, name, "/"});
response.selected.append({state.path, name, "/"});
}
if(state.action == "openObject" && batched.size() == 1) {
string name = batched[0].text();
if(!isMatch(name) && isFolder(name)) return setPath({state.path, name});
response.selected.append(string{state.path, name, isFolder(name) ? "/" : ""});
response.selected.append({state.path, name, isFolder(name) ? "/" : ""});
}
if(state.action == "saveFile") {
@ -85,7 +87,7 @@ auto BrowserDialogWindow::accept() -> void {
if(file::exists({state.path, name})) {
if(MessageDialog("File already exists. Overwrite it?").question() != "Yes") return;
}
response.selected.append(string{state.path, name});
response.selected.append({state.path, name});
}
if(state.action == "selectFolder") {
@ -93,7 +95,7 @@ auto BrowserDialogWindow::accept() -> void {
response.selected.append(state.path);
} else if(batched.size() == 1) {
string name = batched[0].text();
if(isFolder(name)) response.selected.append(string{state.path, name, "/"});
if(isFolder(name)) response.selected.append({state.path, name, "/"});
}
}
@ -137,9 +139,13 @@ auto BrowserDialogWindow::change() -> void {
acceptButton.setEnabled(batched.size() == 1);
}
if(state.action == "saveFile") {
string result;
if(batched.size() == 1) {
string name = batched[0].text();
if(!isFolder(name)) fileName.setText(name).doChange();
if(!isFolder(name)) result = name;
}
if(result != fileName.text()) {
fileName.setText(result).doChange();
}
}
if(state.action == "selectFolder") {
@ -165,6 +171,14 @@ auto BrowserDialogWindow::context() -> void {
contextMenu.setVisible();
}
auto BrowserDialogWindow::isObject(const string& name) -> bool {
return inode::exists({state.path, name});
}
auto BrowserDialogWindow::isFile(const string& name) -> bool {
return file::exists({state.path, name});
}
auto BrowserDialogWindow::isFolder(const string& name) -> bool {
return directory::exists({state.path, name});
}
@ -217,8 +231,21 @@ auto BrowserDialogWindow::run() -> BrowserDialog::Response {
iconSearch.scale(16_sx, 16_sy);
searchButton.setIcon(iconSearch).setBordered(false).onActivate([&] { setPath(state.path, fileName.text()); });
fileName.onActivate([&] {
string name = fileName.text();
if((state.action == "openFile" || state.action == "openFiles") && isFile(name)) {
response.selected.append({state.path, name});
return (void)window.setModal(false);
}
if((state.action == "openFolder" || state.action == "selectFolder") && isFolder(name)) {
response.selected.append({state.path, name});
return (void)window.setModal(false);
}
if(state.action == "openObject" && isObject(name)) {
response.selected.append({state.path, name});
return (void)window.setModal(false);
}
if(state.action == "saveFile") return accept();
setPath(state.path, fileName.text());
setPath(state.path, name);
}).onChange([&] {
auto name = fileName.text();
if(state.action == "saveFile") acceptButton.setEnabled(name && !isFolder(name));

View File

@ -447,18 +447,26 @@ static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT ms
#if defined(Hiro_TableView)
case AppMessage::TableView_doPaint: {
if(auto tableView = (mTableView*)lparam) {
if(auto self = tableView->self()) InvalidateRect(self->hwnd, nullptr, true);
if(auto self = tableView->self()) {
InvalidateRect(self->hwnd, nullptr, true);
}
}
break;
}
case AppMessage::TableView_onActivate: {
if(auto tableView = (mTableView*)lparam) tableView->doActivate({});
if(auto tableView = (mTableView*)lparam) {
if(auto self = tableView->self()) {
tableView->doActivate(self->activateCell);
}
}
break;
}
case AppMessage::TableView_onChange: {
if(auto tableView = (mTableView*)lparam) tableView->doChange();
if(auto tableView = (mTableView*)lparam) {
tableView->doChange();
}
}
#endif
}

View File

@ -105,6 +105,21 @@ auto pTableView::onActivate(LPARAM lparam) -> void {
auto nmlistview = (LPNMLISTVIEW)lparam;
if(ListView_GetSelectedCount(hwnd) == 0) return;
if(!locked()) {
activateCell = TableViewCell();
LVHITTESTINFO hitTest{};
GetCursorPos(&hitTest.pt);
ScreenToClient(nmlistview->hdr.hwndFrom, &hitTest.pt);
ListView_SubItemHitTest(nmlistview->hdr.hwndFrom, &hitTest);
if(hitTest.flags & LVHT_ONITEM) {
int row = hitTest.iItem;
if(row >= 0 && row < state().items.size()) {
int column = hitTest.iSubItem;
if(column >= 0 && column < state().columns.size()) {
auto item = state().items[row];
activateCell = item->cell(column);
}
}
}
//LVN_ITEMACTIVATE is not re-entrant until DispatchMessage() completes
//thus, we don't call self().doActivate() here
PostMessageOnce(_parentHandle(), AppMessage::TableView_onActivate, 0, (LPARAM)&reference);

View File

@ -35,6 +35,7 @@ struct pTableView : pWidget {
auto _setIcons() -> void;
auto _width(unsigned column) -> unsigned;
TableViewCell activateCell;
HIMAGELIST imageList = 0;
vector<image> icons;
};