mirror of https://github.com/bsnes-emu/bsnes.git
v108.3
* 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:
parent
a7b30b069c
commit
bc7456246c
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -35,6 +35,7 @@ struct pTableView : pWidget {
|
|||
auto _setIcons() -> void;
|
||||
auto _width(unsigned column) -> unsigned;
|
||||
|
||||
TableViewCell activateCell;
|
||||
HIMAGELIST imageList = 0;
|
||||
vector<image> icons;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue