bool ListBox::onProcessMessage(Message* msg) { switch (msg->type()) { case kOpenMessage: centerScroll(); break; case kMouseDownMessage: captureMouse(); case kMouseMoveMessage: if (hasCapture()) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); int select = getSelectedIndex(); View* view = View::getView(this); bool pick_item = true; if (view) { gfx::Rect vp = view->getViewportBounds(); if (mousePos.y < vp.y) { int num = MAX(1, (vp.y - mousePos.y) / 8); selectIndex(select-num); pick_item = false; } else if (mousePos.y >= vp.y + vp.h) { int num = MAX(1, (mousePos.y - (vp.y+vp.h-1)) / 8); selectIndex(select+num); pick_item = false; } } if (pick_item) { Widget* picked; if (view) { picked = view->getViewport()->pick(mousePos); } else { picked = pick(mousePos); } /* if the picked widget is a child of the list, select it */ if (picked && hasChild(picked)) { if (ListItem* pickedItem = dynamic_cast<ListItem*>(picked)) selectChild(pickedItem); } } return true; } break; case kMouseUpMessage: releaseMouse(); break; case kMouseWheelMessage: { View* view = View::getView(this); if (view) { gfx::Point scroll = view->getViewScroll(); scroll += static_cast<MouseMessage*>(msg)->wheelDelta() * getTextHeight()*3; view->setViewScroll(scroll); } break; } case kKeyDownMessage: if (hasFocus() && !getChildren().empty()) { int select = getSelectedIndex(); View* view = View::getView(this); int bottom = MAX(0, getChildren().size()-1); KeyMessage* keymsg = static_cast<KeyMessage*>(msg); switch (keymsg->scancode()) { case kKeyUp: // Select previous element. if (select >= 0) select--; // Or select the bottom of the list if there is no // selected item. else select = bottom; break; case kKeyDown: select++; break; case kKeyHome: select = 0; break; case kKeyEnd: select = bottom; break; case kKeyPageUp: if (view) { gfx::Rect vp = view->getViewportBounds(); select -= vp.h / getTextHeight(); } else select = 0; break; case kKeyPageDown: if (view) { gfx::Rect vp = view->getViewportBounds(); select += vp.h / getTextHeight(); } else select = bottom; break; case kKeyLeft: case kKeyRight: if (view) { gfx::Rect vp = view->getViewportBounds(); gfx::Point scroll = view->getViewScroll(); int sgn = (keymsg->scancode() == kKeyLeft) ? -1: 1; scroll.x += vp.w/2*sgn; view->setViewScroll(scroll); } break; default: return Widget::onProcessMessage(msg); } selectIndex(MID(0, select, bottom)); return true; } break; case kDoubleClickMessage: onDoubleClickItem(); return true; } return Widget::onProcessMessage(msg); }
bool ButtonBase::onProcessMessage(Message* msg) { switch (msg->type()) { case kFocusEnterMessage: case kFocusLeaveMessage: if (isEnabled()) { if (m_behaviorType == kButtonWidget) { // Deselect the widget (maybe the user press the key, but // before release it, changes the focus). if (isSelected()) setSelected(false); } // TODO theme specific stuff invalidate(); } break; case kKeyDownMessage: { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); if (isEnabled() && isVisible()) { bool mnemonicPressed = ((msg->altPressed() || msg->cmdPressed()) && isMnemonicPressed(keymsg)); // For kButtonWidget if (m_behaviorType == kButtonWidget) { // Has focus and press enter/space if (hasFocus()) { if ((scancode == kKeyEnter) || (scancode == kKeyEnterPad) || (scancode == kKeySpace)) { setSelected(true); return true; } } // Check if the user pressed mnemonic. if (mnemonicPressed) { setSelected(true); return true; } // Magnetic widget catches ENTERs else if (isFocusMagnet() && ((scancode == kKeyEnter) || (scancode == kKeyEnterPad))) { manager()->setFocus(this); // Dispatch focus movement messages (because the buttons // process them) manager()->dispatchMessages(); setSelected(true); return true; } } // For kCheckWidget or kRadioWidget else { /* if the widget has the focus and the user press space or if the user press Alt+the underscored letter of the button */ if ((hasFocus() && (scancode == kKeySpace)) || mnemonicPressed) { if (m_behaviorType == kCheckWidget) { // Swap the select status setSelected(!isSelected()); invalidate(); } else if (m_behaviorType == kRadioWidget) { if (!isSelected()) { setSelected(true); } } return true; } } } break; } case kKeyUpMessage: if (isEnabled()) { if (m_behaviorType == kButtonWidget) { if (isSelected()) { generateButtonSelectSignal(); return true; } } } break; case kMouseDownMessage: switch (m_behaviorType) { case kButtonWidget: if (isEnabled()) { setSelected(true); m_pressedStatus = isSelected(); captureMouse(); } return true; case kCheckWidget: if (isEnabled()) { setSelected(!isSelected()); m_pressedStatus = isSelected(); captureMouse(); } return true; case kRadioWidget: if (isEnabled()) { if (!isSelected()) { m_handleSelect = false; setSelected(true); m_handleSelect = true; m_pressedStatus = isSelected(); captureMouse(); } } return true; } break; case kMouseUpMessage: if (hasCapture()) { releaseMouse(); if (hasMouseOver()) { switch (m_behaviorType) { case kButtonWidget: generateButtonSelectSignal(); break; case kCheckWidget: { // Fire onClick() event Event ev(this); onClick(ev); invalidate(); } break; case kRadioWidget: { setSelected(false); setSelected(true); // Fire onClick() event Event ev(this); onClick(ev); } break; } } return true; } break; case kMouseMoveMessage: if (isEnabled() && hasCapture()) { bool hasMouse = hasMouseOver(); m_handleSelect = false; // Switch state when the mouse go out if ((hasMouse && isSelected() != m_pressedStatus) || (!hasMouse && isSelected() == m_pressedStatus)) { if (hasMouse) setSelected(m_pressedStatus); else setSelected(!m_pressedStatus); } m_handleSelect = true; } break; case kMouseEnterMessage: case kMouseLeaveMessage: // TODO theme stuff if (isEnabled()) invalidate(); break; } return Widget::onProcessMessage(msg); }
bool PopupWindow::onProcessMessage(Message* msg) { switch (msg->type()) { case kCloseMessage: stopFilteringMessages(); break; case kMouseLeaveMessage: if (m_hotRegion.isEmpty() && !isMoveable()) closeWindow(NULL); break; case kKeyDownMessage: if (m_filtering) { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); if (scancode == kKeyEsc || scancode == kKeyEnter || scancode == kKeyEnterPad) { closeWindow(NULL); } // If we are filtering messages we don't propagate key-events // to other widgets. As we're a popup window and we're // filtering messages, the user shouldn't be able to start // other actions pressing keyboard shortcuts. return false; } break; case kMouseDownMessage: if (m_filtering) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); switch (m_clickBehavior) { // If the user click outside the window, we have to close // the tooltip window. case kCloseOnClickInOtherWindow: { Widget* picked = pick(mousePos); if (!picked || picked->getRoot() != this) { closeWindow(NULL); } break; } case kCloseOnClickOutsideHotRegion: if (!m_hotRegion.contains(mousePos)) { closeWindow(NULL); } break; } } break; case kMouseMoveMessage: if (!isMoveable() && !m_hotRegion.isEmpty() && getManager()->getCapture() == NULL) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); // If the mouse is outside the hot-region we have to close the // window. if (!m_hotRegion.contains(mousePos)) closeWindow(NULL); } break; } return Window::onProcessMessage(msg); }
bool Entry::onProcessMessage(Message* msg) { switch (msg->type()) { case kTimerMessage: if (hasFocus() && static_cast<TimerMessage*>(msg)->timer() == &m_timer) { // Blinking caret m_state = m_state ? false: true; invalidate(); } break; case kFocusEnterMessage: m_timer.start(); m_state = true; invalidate(); if (m_lock_selection) { m_lock_selection = false; } else { selectAllText(); m_recent_focused = true; } break; case kFocusLeaveMessage: invalidate(); m_timer.stop(); if (!m_lock_selection) deselectText(); m_recent_focused = false; break; case kKeyDownMessage: if (hasFocus() && !isReadOnly()) { // Command to execute EntryCmd cmd = EntryCmd::NoOp; KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); switch (scancode) { case kKeyLeft: if (msg->ctrlPressed()) cmd = EntryCmd::BackwardWord; else cmd = EntryCmd::BackwardChar; break; case kKeyRight: if (msg->ctrlPressed()) cmd = EntryCmd::ForwardWord; else cmd = EntryCmd::ForwardChar; break; case kKeyHome: cmd = EntryCmd::BeginningOfLine; break; case kKeyEnd: cmd = EntryCmd::EndOfLine; break; case kKeyDel: if (msg->shiftPressed()) cmd = EntryCmd::Cut; else cmd = EntryCmd::DeleteForward; break; case kKeyInsert: if (msg->shiftPressed()) cmd = EntryCmd::Paste; else if (msg->ctrlPressed()) cmd = EntryCmd::Copy; break; case kKeyBackspace: cmd = EntryCmd::DeleteBackward; break; default: // Map common Windows shortcuts for Cut/Copy/Paste #if defined __APPLE__ if (msg->onlyCmdPressed()) #else if (msg->onlyCtrlPressed()) #endif { switch (scancode) { case kKeyX: cmd = EntryCmd::Cut; break; case kKeyC: cmd = EntryCmd::Copy; break; case kKeyV: cmd = EntryCmd::Paste; break; } } else if (keymsg->unicodeChar() >= 32) { // Ctrl and Alt must be unpressed to insert a character // in the text-field. if ((msg->keyModifiers() & (kKeyCtrlModifier | kKeyAltModifier)) == 0) { cmd = EntryCmd::InsertChar; } } break; } if (cmd == EntryCmd::NoOp) break; executeCmd(cmd, keymsg->unicodeChar(), (msg->shiftPressed()) ? true: false); return true; } break; case kMouseDownMessage: captureMouse(); case kMouseMoveMessage: if (hasCapture()) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); base::utf8_const_iterator utf8_end = base::utf8_const_iterator(getText().end()); int textlen = base::utf8_length(getText()); int c, x; bool move = true; bool is_dirty = false; // Backward scroll if (mousePos.x < getBounds().x) { if (m_scroll > 0) { m_caret = --m_scroll; move = false; is_dirty = true; invalidate(); } } // Forward scroll else if (mousePos.x >= getBounds().x2()) { if (m_scroll < textlen - getAvailableTextLength()) { m_scroll++; x = getBounds().x + this->border_width.l; for (c=m_scroll; utf8_begin != utf8_end; ++c) { int ch = (c < textlen ? *(utf8_begin+c) : ' '); x += getFont()->charWidth(ch); if (x > getBounds().x2()-this->border_width.r) { c--; break; } } m_caret = c; move = false; is_dirty = true; invalidate(); } } c = getCaretFromMouse(static_cast<MouseMessage*>(msg)); if (static_cast<MouseMessage*>(msg)->left() || (move && !isPosInSelection(c))) { // Move caret if (move) { if (m_caret != c) { m_caret = c; is_dirty = true; invalidate(); } } // Move selection if (m_recent_focused) { m_recent_focused = false; m_select = m_caret; } else if (msg->type() == kMouseDownMessage) m_select = m_caret; } // Show the caret if (is_dirty) { m_timer.start(); m_state = true; } return true; } break; case kMouseUpMessage: if (hasCapture()) { releaseMouse(); MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); if (mouseMsg->right()) { // This flag is disabled in kFocusEnterMessage message handler. m_lock_selection = true; showEditPopupMenu(mouseMsg->position()); requestFocus(); } } return true; case kDoubleClickMessage: forwardWord(); m_select = m_caret; backwardWord(); invalidate(); return true; case kMouseEnterMessage: case kMouseLeaveMessage: // TODO theme stuff if (isEnabled()) invalidate(); break; } return Widget::onProcessMessage(msg); }
bool IntEntry::onProcessMessage(Message* msg) { switch (msg->type()) { // Reset value if it's out of bounds when focus is lost case kFocusLeaveMessage: setValue(MID(m_min, getValue(), m_max)); deselectText(); break; case kMouseDownMessage: requestFocus(); captureMouse(); openPopup(); selectAllText(); return true; case kMouseMoveMessage: if (hasCapture()) { MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); Widget* pick = manager()->pick(mouseMsg->position()); if (pick == &m_slider) { releaseMouse(); MouseMessage mouseMsg2(kMouseDownMessage, mouseMsg->pointerType(), mouseMsg->buttons(), mouseMsg->modifiers(), mouseMsg->position()); m_slider.sendMessage(&mouseMsg2); } } break; case kMouseWheelMessage: if (isEnabled()) { int oldValue = getValue(); int newValue = oldValue + static_cast<MouseMessage*>(msg)->wheelDelta().x - static_cast<MouseMessage*>(msg)->wheelDelta().y; newValue = MID(m_min, newValue, m_max); if (newValue != oldValue) { setValue(newValue); selectAllText(); } return true; } break; case kKeyDownMessage: if (hasFocus() && !isReadOnly()) { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); int chr = keymsg->unicodeChar(); if (chr >= 32 && (chr < '0' || chr > '9')) { // "Eat" all keys that aren't number return true; } // Else we use the default Entry processing function which // will process keys like Left/Right arrows, clipboard // handling, etc. } break; } return Entry::onProcessMessage(msg); }
bool Entry::onProcessMessage(Message* msg) { switch (msg->type()) { case kTimerMessage: if (hasFocus() && static_cast<TimerMessage*>(msg)->timer() == &m_timer) { // Blinking caret m_state = m_state ? false: true; invalidate(); } break; case kFocusEnterMessage: if (shouldStartTimer(true)) m_timer.start(); m_state = true; invalidate(); if (m_lock_selection) { m_lock_selection = false; } else { selectAllText(); m_recent_focused = true; } // Start processing dead keys if (m_translate_dead_keys) os::instance()->setTranslateDeadKeys(true); break; case kFocusLeaveMessage: invalidate(); m_timer.stop(); if (!m_lock_selection) deselectText(); m_recent_focused = false; // Stop processing dead keys if (m_translate_dead_keys) os::instance()->setTranslateDeadKeys(false); break; case kKeyDownMessage: if (hasFocus() && !isReadOnly()) { // Command to execute EntryCmd cmd = EntryCmd::NoOp; KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); switch (scancode) { case kKeyLeft: if (msg->ctrlPressed() || msg->altPressed()) cmd = EntryCmd::BackwardWord; else if (msg->cmdPressed()) cmd = EntryCmd::BeginningOfLine; else cmd = EntryCmd::BackwardChar; break; case kKeyRight: if (msg->ctrlPressed() || msg->altPressed()) cmd = EntryCmd::ForwardWord; else if (msg->cmdPressed()) cmd = EntryCmd::EndOfLine; else cmd = EntryCmd::ForwardChar; break; case kKeyHome: cmd = EntryCmd::BeginningOfLine; break; case kKeyEnd: cmd = EntryCmd::EndOfLine; break; case kKeyDel: if (msg->shiftPressed()) cmd = EntryCmd::Cut; else if (msg->ctrlPressed()) cmd = EntryCmd::DeleteForwardToEndOfLine; else cmd = EntryCmd::DeleteForward; break; case kKeyInsert: if (msg->shiftPressed()) cmd = EntryCmd::Paste; else if (msg->ctrlPressed()) cmd = EntryCmd::Copy; break; case kKeyBackspace: if (msg->ctrlPressed()) cmd = EntryCmd::DeleteBackwardWord; else cmd = EntryCmd::DeleteBackward; break; default: // Map common macOS/Windows shortcuts for Cut/Copy/Paste/Select all #if defined __APPLE__ if (msg->onlyCmdPressed()) #else if (msg->onlyCtrlPressed()) #endif { switch (scancode) { case kKeyX: cmd = EntryCmd::Cut; break; case kKeyC: cmd = EntryCmd::Copy; break; case kKeyV: cmd = EntryCmd::Paste; break; case kKeyA: cmd = EntryCmd::SelectAll; break; } } break; } if (cmd == EntryCmd::NoOp) { if (keymsg->unicodeChar() >= 32) { executeCmd(EntryCmd::InsertChar, keymsg->unicodeChar(), (msg->shiftPressed()) ? true: false); // Select dead-key if (keymsg->isDeadKey()) { if (lastCaretPos() < m_maxsize) selectText(m_caret-1, m_caret); } return true; } // Consume all key down of modifiers only, e.g. so the user // can press first "Ctrl" key, and then "Ctrl+C" // combination. else if (keymsg->scancode() >= kKeyFirstModifierScancode) { return true; } else { break; // Propagate to manager } } executeCmd(cmd, keymsg->unicodeChar(), (msg->shiftPressed()) ? true: false); return true; } break; case kMouseDownMessage: captureMouse(); case kMouseMoveMessage: if (hasCapture()) { bool is_dirty = false; int c = getCaretFromMouse(static_cast<MouseMessage*>(msg)); if (static_cast<MouseMessage*>(msg)->left() || !isPosInSelection(c)) { // Move caret if (m_caret != c) { setCaretPos(c); is_dirty = true; invalidate(); } // Move selection if (m_recent_focused) { m_recent_focused = false; m_select = m_caret; } else if (msg->type() == kMouseDownMessage) m_select = m_caret; } // Show the caret if (is_dirty) { if (shouldStartTimer(true)) m_timer.start(); m_state = true; } return true; } break; case kMouseUpMessage: if (hasCapture()) { releaseMouse(); MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); if (mouseMsg->right()) { // This flag is disabled in kFocusEnterMessage message handler. m_lock_selection = true; showEditPopupMenu(mouseMsg->position()); requestFocus(); } } return true; case kDoubleClickMessage: forwardWord(); m_select = m_caret; backwardWord(); invalidate(); return true; case kMouseEnterMessage: case kMouseLeaveMessage: // TODO theme stuff if (isEnabled()) invalidate(); break; } return Widget::onProcessMessage(msg); }
bool ComboBoxEntry::onProcessMessage(Message* msg) { switch (msg->type()) { case kKeyDownMessage: if (hasFocus()) { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); if (!m_comboBox->isEditable()) { if (scancode == kKeySpace || scancode == kKeyEnter || scancode == kKeyEnterPad) { m_comboBox->switchListBox(); return true; } } else { if (scancode == kKeyEnter || scancode == kKeyEnterPad) { m_comboBox->switchListBox(); return true; } } } break; case kMouseDownMessage: if (m_comboBox->isClickOpen()) { m_comboBox->switchListBox(); } if (m_comboBox->isEditable()) { getManager()->setFocus(this); } else { captureMouse(); return true; } break; case kMouseUpMessage: if (hasCapture()) releaseMouse(); break; case kMouseMoveMessage: if (hasCapture()) { MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); Widget* pick = getManager()->pick(mouseMsg->position()); Widget* listbox = m_comboBox->m_listbox; if (pick != NULL && (pick == listbox || pick->hasAncestor(listbox))) { releaseMouse(); MouseMessage mouseMsg2(kMouseDownMessage, mouseMsg->buttons(), mouseMsg->position()); pick->sendMessage(&mouseMsg2); return true; } } break; } return Entry::onProcessMessage(msg); }
bool ButtonSet::Item::onProcessMessage(ui::Message* msg) { switch (msg->type()) { case kFocusEnterMessage: case kFocusLeaveMessage: if (isEnabled()) { // TODO theme specific stuff invalidate(); } break; case ui::kKeyDownMessage: if (isEnabled() && hasText()) { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); bool mnemonicPressed = (msg->altPressed() && getMnemonicChar() && getMnemonicChar() == tolower(keymsg->unicodeChar())); if (mnemonicPressed || (hasFocus() && keymsg->scancode() == kKeySpace)) { buttonSet()->setSelectedItem(this); buttonSet()->onItemChange(this); } } break; case ui::kMouseDownMessage: captureMouse(); buttonSet()->setSelectedItem(this); invalidate(); if (static_cast<MouseMessage*>(msg)->left() && !buttonSet()->m_triggerOnMouseUp) { buttonSet()->onItemChange(this); } break; case ui::kMouseUpMessage: if (hasCapture()) { releaseMouse(); invalidate(); if (static_cast<MouseMessage*>(msg)->left()) { if (buttonSet()->m_triggerOnMouseUp) buttonSet()->onItemChange(this); } else if (static_cast<MouseMessage*>(msg)->right()) { buttonSet()->onRightClick(this); } } break; case ui::kMouseMoveMessage: if (hasCapture()) { if (buttonSet()->m_offerCapture) offerCapture(static_cast<ui::MouseMessage*>(msg), buttonset_item_type()); } break; case ui::kMouseLeaveMessage: case ui::kMouseEnterMessage: invalidate(); break; } return Widget::onProcessMessage(msg); }
bool PopupWindow::onProcessMessage(Message* msg) { switch (msg->type()) { // There are cases where startFilteringMessages() is called when a // kCloseMessage for this same PopupWindow is enqueued. Processing // the kOpenMessage we ensure that the popup will be filtering // messages if it's needed when it's visible (as kCloseMessage and // kOpenMessage must be enqueued in the correct order). case kOpenMessage: if (!isMoveable()) startFilteringMessages(); break; case kCloseMessage: stopFilteringMessages(); break; case kMouseLeaveMessage: if (m_hotRegion.isEmpty() && !isMoveable()) closeWindow(nullptr); break; case kKeyDownMessage: if (m_filtering) { KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keymsg->scancode(); if (scancode == kKeyEsc) closeWindow(nullptr); if (m_enterBehavior == EnterBehavior::CloseOnEnter && (scancode == kKeyEnter || scancode == kKeyEnterPad)) { closeWindow(this); return true; } } break; case kMouseDownMessage: if (m_filtering && manager()->getTopWindow() == this) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); switch (m_clickBehavior) { // If the user click outside the window, we have to close // the tooltip window. case ClickBehavior::CloseOnClickInOtherWindow: { Widget* picked = pick(mousePos); if (!picked || picked->window() != this) { closeWindow(NULL); } break; } case ClickBehavior::CloseOnClickOutsideHotRegion: if (!m_hotRegion.contains(mousePos)) { closeWindow(NULL); } break; } } break; case kMouseMoveMessage: if (!isMoveable() && !m_hotRegion.isEmpty() && manager()->getCapture() == NULL) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); // If the mouse is outside the hot-region we have to close the // window. if (!m_hotRegion.contains(mousePos)) closeWindow(NULL); } break; } return Window::onProcessMessage(msg); }
bool FileList::onProcessMessage(Message* msg) { switch (msg->type()) { case kMouseDownMessage: captureMouse(); case kMouseMoveMessage: if (hasCapture()) { MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); int th = getTextHeight(); int y = getBounds().y; IFileItem* old_selected = m_selected; m_selected = NULL; // rows for (FileItemList::iterator it=m_list.begin(); it!=m_list.end(); ++it) { IFileItem* fi = *it; gfx::Size itemSize = getFileItemSize(fi); if (((mouseMsg->position().y >= y) && (mouseMsg->position().y < y+th+4*jguiscale())) || (it == m_list.begin() && mouseMsg->position().y < y) || (it == m_list.end()-1 && mouseMsg->position().y >= y+th+4*jguiscale())) { m_selected = fi; makeSelectedFileitemVisible(); break; } y += itemSize.h; } if (old_selected != m_selected) { generatePreviewOfSelectedItem(); invalidate(); // Emit "FileSelected" event. onFileSelected(); } } break; case kMouseUpMessage: if (hasCapture()) { releaseMouse(); } break; case kKeyDownMessage: if (hasFocus()) { KeyMessage* keyMsg = static_cast<KeyMessage*>(msg); KeyScancode scancode = keyMsg->scancode(); int unicodeChar = keyMsg->unicodeChar(); int select = getSelectedIndex(); View* view = View::getView(this); int bottom = m_list.size(); switch (scancode) { case kKeyUp: if (select >= 0) select--; else select = 0; break; case kKeyDown: if (select >= 0) select++; else select = 0; break; case kKeyHome: select = 0; break; case kKeyEnd: select = bottom-1; break; case kKeyPageUp: case kKeyPageDown: { int sgn = (scancode == kKeyPageUp) ? -1: 1; gfx::Rect vp = view->getViewportBounds(); if (select < 0) select = 0; select += sgn * vp.h / (getTextHeight()+4*jguiscale()); break; } case kKeyLeft: case kKeyRight: if (select >= 0) { gfx::Rect vp = view->getViewportBounds(); int sgn = (scancode == kKeyLeft) ? -1: 1; gfx::Point scroll = view->getViewScroll(); scroll.x += vp.w/2*sgn; view->setViewScroll(scroll); } break; case kKeyEnter: case kKeyEnterPad: if (m_selected) { if (m_selected->isBrowsable()) { setCurrentFolder(m_selected); return true; } if (m_selected->isFolder()) { // Do nothing (is a folder but not browseable). return true; } else { // Emit "FileAccepted" event. onFileAccepted(); return true; } } else return Widget::onProcessMessage(msg); case kKeyBackspace: goUp(); return true; default: if (unicodeChar == ' ' || (utolower(unicodeChar) >= 'a' && utolower(unicodeChar) <= 'z') || (unicodeChar >= '0' && unicodeChar <= '9')) { if (ui::clock() - m_isearchClock > ISEARCH_KEYPRESS_INTERVAL_MSECS) m_isearch.clear(); m_isearch.push_back(unicodeChar); int i, chrs = m_isearch.size(); FileItemList::iterator link = m_list.begin() + ((select >= 0) ? select: 0); for (i=MAX(select, 0); i<bottom; ++i, ++link) { IFileItem* fi = *link; if (ustrnicmp(fi->getDisplayName().c_str(), m_isearch.c_str(), chrs) == 0) { select = i; break; } } m_isearchClock = ui::clock(); // Go to selectIndex... } else return Widget::onProcessMessage(msg); } if (bottom > 0) selectIndex(MID(0, select, bottom-1)); return true; } break; case kMouseWheelMessage: { View* view = View::getView(this); if (view) { gfx::Point scroll = view->getViewScroll(); scroll += static_cast<MouseMessage*>(msg)->wheelDelta() * 3*(getTextHeight()+4*jguiscale()); view->setViewScroll(scroll); } break; } case kDoubleClickMessage: if (m_selected) { if (m_selected->isBrowsable()) { setCurrentFolder(m_selected); return true; } else { onFileAccepted(); // Emit "FileAccepted" event. return true; } } break; } return Widget::onProcessMessage(msg); }