Пример #1
0
void ListBox::selectChild(Widget* item)
{
  for (Widget* child : getChildren()) {
    if (child->isSelected()) {
      if (item && child == item)
        return;

      child->setSelected(false);
    }
  }

  if (item) {
    View* view = View::getView(this);

    item->setSelected(true);

    if (view) {
      gfx::Rect vp = view->getViewportBounds();
      gfx::Point scroll = view->getViewScroll();

      if (item->getBounds().y < vp.y)
        scroll.y = item->getBounds().y - getBounds().y;
      else if (item->getBounds().y > vp.y + vp.h - item->getBounds().h)
        scroll.y = (item->getBounds().y - getBounds().y
                    - vp.h + item->getBounds().h);

      view->setViewScroll(scroll);
    }
  }

  onChangeSelectedItem();
}
Пример #2
0
void PaletteView::update_scroll(int color)
{
  View* view = View::getView(this);
  if (!view)
    return;

  gfx::Rect vp = view->getViewportBounds();
  gfx::Point scroll;
  int x, y, cols;
  div_t d;

  scroll = view->getViewScroll();

  d = div(Palette::MaxColors, m_columns);
  cols = m_columns;

  y = (m_boxsize+this->child_spacing) * (color / cols);
  x = (m_boxsize+this->child_spacing) * (color % cols);

  if (scroll.x > x)
    scroll.x = x;
  else if (scroll.x+vp.w-m_boxsize-2 < x)
    scroll.x = x-vp.w+m_boxsize+2;

  if (scroll.y > y)
    scroll.y = y;
  else if (scroll.y+vp.h-m_boxsize-2 < y)
    scroll.y = y-vp.h+m_boxsize+2;

  view->setViewScroll(scroll);
}
Пример #3
0
void FileList::makeSelectedFileitemVisible()
{
  View* view = View::getView(this);
  gfx::Rect vp = view->getViewportBounds();
  gfx::Point scroll = view->getViewScroll();
  int th = getTextHeight();
  int y = getBounds().y;

  // rows
  for (FileItemList::iterator
         it=m_list.begin();
       it!=m_list.end(); ++it) {
    IFileItem* fi = *it;
    gfx::Size itemSize = getFileItemSize(fi);

    if (fi == m_selected) {
      if (y < vp.y)
        scroll.y = y - getBounds().y;
      else if (y > vp.y + vp.h - (th+4*jguiscale()))
        scroll.y = y - getBounds().y - vp.h + (th+4*jguiscale());

      view->setViewScroll(scroll);
      break;
    }

    y += itemSize.h;
  }
}
Пример #4
0
// Setup the scroll to center the selected item in the viewport
void ListBox::centerScroll()
{
  View* view = View::getView(this);
  Widget* item = getSelectedChild();

  if (view && item) {
    gfx::Rect vp = view->getViewportBounds();
    gfx::Point scroll = view->getViewScroll();

    scroll.y = ((item->getBounds().y - getBounds().y)
                - vp.h/2 + item->getBounds().h/2);

    view->setViewScroll(scroll);
  }
}
Пример #5
0
void ListBox::makeChildVisible(Widget* child)
{
  View* view = View::getView(this);
  if (!view)
    return;

  gfx::Point scroll = view->getViewScroll();
  gfx::Rect vp = view->getViewportBounds();

  if (child->getBounds().y < vp.y)
    scroll.y = child->getBounds().y - getBounds().y;
  else if (child->getBounds().y > vp.y + vp.h - child->getBounds().h)
    scroll.y = (child->getBounds().y - getBounds().y
                - vp.h + child->getBounds().h);

  view->setViewScroll(scroll);
}
Пример #6
0
bool TextBox::onProcessMessage(Message* msg)
{
  switch (msg->type) {

    case JM_DRAW:
      getTheme()->draw_textbox(this, &msg->draw.rect);
      return true;

    case JM_SIGNAL:
      if (msg->signal.num == JI_SIGNAL_SET_TEXT) {
        View* view = View::getView(this);
        if (view)
          view->updateView();
      }
      break;

    case JM_KEYPRESSED:
      if (hasFocus()) {
        View* view = View::getView(this);
        if (view) {
          gfx::Rect vp = view->getViewportBounds();
          gfx::Point scroll = view->getViewScroll();
          int textheight = jwidget_get_text_height(this);

          switch (msg->key.scancode) {

            case KEY_LEFT:
              scroll.x -= vp.w/2;
              view->setViewScroll(scroll);
              break;

            case KEY_RIGHT:
              scroll.x += vp.w/2;
              view->setViewScroll(scroll);
              break;

            case KEY_UP:
              scroll.y -= vp.h/2;
              view->setViewScroll(scroll);
              break;

            case KEY_DOWN:
              scroll.y += vp.h/2;
              view->setViewScroll(scroll);
              break;

            case KEY_PGUP:
              scroll.y -= (vp.h-textheight);
              view->setViewScroll(scroll);
              break;

            case KEY_PGDN:
              scroll.y += (vp.h-textheight);
              view->setViewScroll(scroll);
              break;

            case KEY_HOME:
              scroll.y = 0;
              view->setViewScroll(scroll);
              break;

            case KEY_END:
              scroll.y = jrect_h(this->rc) - vp.h;
              view->setViewScroll(scroll);
              break;

            default:
              return false;
          }
        }
        return true;
      }
      break;

    case JM_BUTTONPRESSED: {
      View* view = View::getView(this);
      if (view) {
        captureMouse();
        jmouse_set_cursor(JI_CURSOR_SCROLL);
        return true;
      }
      break;
    }

    case JM_MOTION: {
      View* view = View::getView(this);
      if (view && hasCapture()) {
        gfx::Rect vp = view->getViewportBounds();
        gfx::Point scroll = view->getViewScroll();

        scroll.x += jmouse_x(1) - jmouse_x(0);
        scroll.y += jmouse_y(1) - jmouse_y(0);

        view->setViewScroll(scroll);

        jmouse_control_infinite_scroll(vp);
      }
      break;
    }

    case JM_BUTTONRELEASED: {
      View* view = View::getView(this);
      if (view && hasCapture()) {
        releaseMouse();
        jmouse_set_cursor(JI_CURSOR_NORMAL);
        return true;
      }
      break;
    }

    case JM_WHEEL: {
      View* view = View::getView(this);
      if (view) {
        gfx::Point scroll = view->getViewScroll();

        scroll.y += (jmouse_z(1) - jmouse_z(0)) * jwidget_get_text_height(this)*3;

        view->setViewScroll(scroll);
      }
      break;
    }
  }

  return Widget::onProcessMessage(msg);
}
Пример #7
0
bool PaletteView::onProcessMessage(Message* msg)
{
  switch (msg->type) {

    case JM_SETPOS:
      if (!m_isUpdatingColumns) {
        m_isUpdatingColumns = true;
        View* view = View::getView(this);
        if (view) {
          int columns =
            (view->getViewportBounds().w-this->child_spacing*2)
            / (m_boxsize+this->child_spacing);
          setColumns(MID(1, columns, Palette::MaxColors));
        }
        m_isUpdatingColumns = false;
      }
      break;

    case JM_DRAW: {
      div_t d = div(Palette::MaxColors, m_columns);
      int cols = m_columns;
      int rows = d.quot + ((d.rem)? 1: 0);
      int x, y, u, v;
      int c, color;
      BITMAP *bmp;
      Palette* palette = get_current_palette();
      int bordercolor = makecol(255, 255, 255);

      bmp = create_bitmap(jrect_w(this->rc), jrect_h(this->rc));
      clear_to_color(bmp, makecol(0 , 0, 0));

      y = this->border_width.t;
      c = 0;

      for (v=0; v<rows; v++) {
        x = this->border_width.l;

        for (u=0; u<cols; u++) {
          if (c >= palette->size())
            break;

          if (bitmap_color_depth(ji_screen) == 8)
            color = c;
          else
            color = makecol_depth
              (bitmap_color_depth(ji_screen),
               _rgba_getr(palette->getEntry(c)),
               _rgba_getg(palette->getEntry(c)),
               _rgba_getb(palette->getEntry(c)));

          rectfill(bmp, x, y, x+m_boxsize-1, y+m_boxsize-1, color);

          if (m_selectedEntries[c]) {
            const int max = Palette::MaxColors;
            bool top    = (c >= m_columns            && c-m_columns >= 0  ? m_selectedEntries[c-m_columns]: false);
            bool bottom = (c < max-m_columns         && c+m_columns < max ? m_selectedEntries[c+m_columns]: false);
            bool left   = ((c%m_columns)>0           && c-1         >= 0  ? m_selectedEntries[c-1]: false);
            bool right  = ((c%m_columns)<m_columns-1 && c+1         < max ? m_selectedEntries[c+1]: false);

            if (!top) hline(bmp, x-1, y-1, x+m_boxsize, bordercolor);
            if (!bottom) hline(bmp, x-1, y+m_boxsize, x+m_boxsize, bordercolor);
            if (!left) vline(bmp, x-1, y-1, y+m_boxsize, bordercolor);
            if (!right) vline(bmp, x+m_boxsize, y-1, y+m_boxsize, bordercolor);
          }

          x += m_boxsize+this->child_spacing;
          c++;
        }

        y += m_boxsize+this->child_spacing;
      }

      blit(bmp, ji_screen,
           0, 0, this->rc->x1, this->rc->y1, bmp->w, bmp->h);
      destroy_bitmap(bmp);
      return true;
    }

    case JM_BUTTONPRESSED:
      captureMouse();
      /* continue... */

    case JM_MOTION: {
      JRect cpos = jwidget_get_child_rect(this);

      int req_w, req_h;
      request_size(&req_w, &req_h);

      int mouse_x = MID(cpos->x1, msg->mouse.x, cpos->x1+req_w-this->border_width.r-1);
      int mouse_y = MID(cpos->y1, msg->mouse.y, cpos->y1+req_h-this->border_width.b-1);

      jrect_free(cpos);

      app::Color color = getColorByPosition(mouse_x, mouse_y);
      if (color.getType() == app::Color::IndexType) {
        int idx = color.getIndex();

        StatusBar::instance()->showColor(0, "", color, 255);

        if (hasCapture() && idx != m_currentEntry) {
          if (!(msg->any.shifts & KB_CTRL_FLAG))
            clearSelection();

          if (msg->any.shifts & KB_SHIFT_FLAG)
            selectRange(m_rangeAnchor, idx);
          else
            selectColor(idx);

          // Emit signal
          IndexChange(idx);
        }
      }

      if (hasCapture())
        return true;

      break;
    }

    case JM_BUTTONRELEASED:
      releaseMouse();
      return true;

    case JM_WHEEL: {
      View* view = View::getView(this);
      if (view) {
        gfx::Point scroll = view->getViewScroll();
        scroll.y += (jmouse_z(1)-jmouse_z(0)) * 3 * m_boxsize;
        view->setViewScroll(scroll);
      }
      break;
    }

    case JM_MOUSELEAVE:
      StatusBar::instance()->clearText();
      break;

  }

  return Widget::onProcessMessage(msg);
}
Пример #8
0
bool TextBox::onProcessMessage(Message* msg)
{
  switch (msg->type()) {

    case kKeyDownMessage:
      if (hasFocus()) {
        View* view = View::getView(this);
        if (view) {
          gfx::Rect vp = view->getViewportBounds();
          gfx::Point scroll = view->getViewScroll();
          int textheight = getTextHeight();

          switch (static_cast<KeyMessage*>(msg)->scancode()) {

            case kKeyLeft:
              scroll.x -= vp.w/2;
              view->setViewScroll(scroll);
              break;

            case kKeyRight:
              scroll.x += vp.w/2;
              view->setViewScroll(scroll);
              break;

            case kKeyUp:
              scroll.y -= vp.h/2;
              view->setViewScroll(scroll);
              break;

            case kKeyDown:
              scroll.y += vp.h/2;
              view->setViewScroll(scroll);
              break;

            case kKeyPageUp:
              scroll.y -= (vp.h-textheight);
              view->setViewScroll(scroll);
              break;

            case kKeyPageDown:
              scroll.y += (vp.h-textheight);
              view->setViewScroll(scroll);
              break;

            case kKeyHome:
              scroll.y = 0;
              view->setViewScroll(scroll);
              break;

            case kKeyEnd:
              scroll.y = getBounds().h - vp.h;
              view->setViewScroll(scroll);
              break;

            default:
              return Widget::onProcessMessage(msg);
          }
        }
        return true;
      }
      break;

    case kMouseDownMessage: {
      View* view = View::getView(this);
      if (view) {
        captureMouse();
        m_oldPos = static_cast<MouseMessage*>(msg)->position();
        set_mouse_cursor(kScrollCursor);
        return true;
      }
      break;
    }

    case kMouseMoveMessage: {
      View* view = View::getView(this);
      if (view && hasCapture()) {
        gfx::Point scroll = view->getViewScroll();
        gfx::Point newPos = static_cast<MouseMessage*>(msg)->position();

        scroll += m_oldPos - newPos;
        view->setViewScroll(scroll);

        m_oldPos = newPos;
      }
      break;
    }

    case kMouseUpMessage: {
      View* view = View::getView(this);
      if (view && hasCapture()) {
        releaseMouse();
        set_mouse_cursor(kArrowCursor);
        return true;
      }
      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;
    }
  }

  return Widget::onProcessMessage(msg);
}
Пример #9
0
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);
}
Пример #10
0
bool ColorCurveEditor::onProcessMessage(Message* msg)
{
  switch (msg->type()) {

    case kKeyDownMessage: {
      switch (static_cast<KeyMessage*>(msg)->scancode()) {

        case kKeyInsert: {
          int x = SCR2EDIT_X(jmouse_x(0));
          int y = SCR2EDIT_Y(jmouse_y(0));

          // TODO undo?
          m_curve->addPoint(gfx::Point(x, y));

          invalidate();
          CurveEditorChange();
          break;
        }

        case kKeyDel: {
          gfx::Point* point = getClosestPoint(SCR2EDIT_X(jmouse_x(0)),
                                              SCR2EDIT_Y(jmouse_y(0)),
                                              NULL, NULL);

          // TODO undo?
          if (point) {
            m_curve->removePoint(*point);
            m_editPoint = NULL;

            invalidate();
            CurveEditorChange();
          }
          break;
        }

        default:
          return false;
      }
      return true;
    }

    case kPaintMessage: {
      BITMAP *bmp;
      int x, y, u;

      bmp = create_bitmap(getBounds().w, getBounds().h);
      clear_to_color(bmp, makecol (0, 0, 0));

      // Draw border
      rect(bmp, 0, 0, bmp->w-1, bmp->h-1, makecol (255, 255, 0));

      // Draw guides
      for (x=1; x<=3; x++)
        vline(bmp, x*bmp->w/4, 1, bmp->h-2, makecol (128, 128, 0));

      for (y=1; y<=3; y++)
        hline(bmp, 1, y*bmp->h/4, bmp->w-2, makecol (128, 128, 0));

      // Get curve values
      std::vector<int> values(m_x2-m_x1+1);
      m_curve->getValues(m_x1, m_x2, values);

      // Draw curve
      for (x=border_width.l;
           x<getBounds().w-border_width.r; x++) {
        u = SCR2EDIT_X(getBounds().x+x);
        u = MID(m_x1, u, m_x2);

        y = values[u - m_x1];
        y = MID(m_y1, y, m_y2);

        putpixel(bmp, x, EDIT2SCR_Y(y)-getBounds().y,
                 makecol(255, 255, 255));
      }

      // Draw nodes
      for (ColorCurve::iterator it = m_curve->begin(), end = m_curve->end(); it != end; ++it) {
        const gfx::Point& point = *it;

        x = EDIT2SCR_X(point.x) - getBounds().x;
        y = EDIT2SCR_Y(point.y) - getBounds().y;

        rect(bmp, x-2, y-2, x+2, y+2,
             m_editPoint == &point ? makecol(255, 255, 0):
                                     makecol(0, 0, 255));
      }

      // Blit to screen
      blit(bmp, ji_screen, 0, 0, getBounds().x, getBounds().y, bmp->w, bmp->h);
      destroy_bitmap(bmp);
      return true;
    }

    case kMouseDownMessage:
      // Change scroll
      if (msg->shiftPressed()) {
        m_status = STATUS_SCROLLING;
        jmouse_set_cursor(kScrollCursor);
      }
      /* scaling */
/*       else if (msg->ctrlPressed()) { */
/*      m_status = STATUS_SCALING; */
/*      jmouse_set_cursor(kScrollCursor); */
/*       } */
      // Show manual-entry dialog
      else if (static_cast<MouseMessage*>(msg)->right()) {
        gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
        m_editPoint = getClosestPoint(SCR2EDIT_X(mousePos.x),
                                      SCR2EDIT_Y(mousePos.y),
                                      NULL, NULL);
        if (m_editPoint) {
          invalidate();
          this->flushRedraw();

          if (editNodeManually(*m_editPoint))
            CurveEditorChange();

          m_editPoint = NULL;
          invalidate();
        }

        return true;
      }
      // Edit node
      else {
        gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
        m_editPoint = getClosestPoint(SCR2EDIT_X(mousePos.x),
                                      SCR2EDIT_Y(mousePos.y),
                                      &m_editX,
                                      &m_editY);

        m_status = STATUS_MOVING_POINT;
        jmouse_set_cursor(kHandCursor);
      }

      captureMouse();
      // continue in motion message...

    case kMouseMoveMessage:
      if (hasCapture()) {
        switch (m_status) {

          case STATUS_SCROLLING: {
            View* view = View::getView(this);
            gfx::Rect vp = view->getViewportBounds();
            gfx::Point scroll = view->getViewScroll();

            scroll.x += jmouse_x(1)-jmouse_x(0);
            scroll.y += jmouse_y(1)-jmouse_y(0);

            view->setViewScroll(scroll);

            jmouse_control_infinite_scroll(vp);
            break;
          }

          case STATUS_MOVING_POINT:
            if (m_editPoint) {
              gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
              *m_editX = SCR2EDIT_X(mousePos.x);
              *m_editY = SCR2EDIT_Y(mousePos.y);
              *m_editX = MID(m_x1, *m_editX, m_x2);
              *m_editY = MID(m_y1, *m_editY, m_y2);

              // TODO this should be optional
              CurveEditorChange();

              invalidate();
            }
            break;
        }

        return true;
      }
#if 0                           // TODO
      // If the mouse move above a curve_editor, the focus change to
      // this widget immediately
      else if (!jwidget_has_focus(this)) {
        jmanager_set_focus(this);
      }
#endif
      break;

    case kMouseUpMessage:
      if (hasCapture()) {
        releaseMouse();

        switch (m_status) {

          case STATUS_SCROLLING:
            jmouse_set_cursor(kArrowCursor);
            break;

/*        case STATUS_SCALING: */
/*          jmouse_set_cursor(kArrowCursor); */
/*          break; */

          case STATUS_MOVING_POINT:
            jmouse_set_cursor(kArrowCursor);
            CurveEditorChange();

            m_editPoint = NULL;
            invalidate();
            break;
        }

        m_status = STATUS_STANDBY;
        return true;
      }
      break;
  }

  return Widget::onProcessMessage(msg);
}
Пример #11
0
bool PaletteView::onProcessMessage(Message* msg)
{
  switch (msg->type()) {

    case kMouseDownMessage:
      captureMouse();
      /* continue... */

    case kMouseMoveMessage: {
      MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
      gfx::Rect cpos = getChildrenBounds();

      int req_w, req_h;
      request_size(&req_w, &req_h);

      int mouse_x = MID(cpos.x, mouseMsg->position().x, cpos.x+req_w-this->border_width.r-1);
      int mouse_y = MID(cpos.y, mouseMsg->position().y, cpos.y+req_h-this->border_width.b-1);

      app::Color color = getColorByPosition(mouse_x, mouse_y);
      if (color.getType() == app::Color::IndexType) {
        int idx = color.getIndex();

        StatusBar::instance()->showColor(0, "", color, 255);

        if (hasCapture() && idx != m_currentEntry) {
          if (!msg->ctrlPressed())
            clearSelection();

          if (msg->shiftPressed())
            selectRange(m_rangeAnchor, idx);
          else
            selectColor(idx);

          // Emit signal
          IndexChange(idx);
        }
      }

      if (hasCapture())
        return true;

      break;
    }

    case kMouseUpMessage:
      releaseMouse();
      return true;

    case kMouseWheelMessage: {
      View* view = View::getView(this);
      if (view) {
        gfx::Point scroll = view->getViewScroll();
        scroll += static_cast<MouseMessage*>(msg)->wheelDelta() * 3 * m_boxsize;
        view->setViewScroll(scroll);
      }
      break;
    }

    case kMouseLeaveMessage:
      StatusBar::instance()->clearText();
      break;

  }

  return Widget::onProcessMessage(msg);
}
Пример #12
0
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);
}