Subversion Repositories DIN Is Noise

Rev

Rev 964 | Rev 1479 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* item_list.cc
* DIN Is Noise is copyright (c) 2006-2020 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/


#include "item_list.h"
#include "font.h"
#include "input.h"
#include "utils.h"
#include "console.h"
#include "tokenizer.h"
#include <sstream>
using namespace std;

extern int mousex, mouseyy;
extern char BUFFER [];
extern int line_height;

item_list::item_list () {
  cur = hov = -1;
  last = nsel = 0;
  sel_lis = 0; // selection
  set_listener (this); // click
}

void item_list::calc () {
  n = items.size ();
  n_1 = n - 1;
  nums.resize (n);
  for (int i = 0; i < n; ++i) {
    sprintf (BUFFER, " [%d]", i+1);
    nums[i] = BUFFER;
  }
}
void item_list::add (const string& item) {
  items.push_back (item);
  sel.push_back (0);
  calc ();
}

void item_list::remove (int i) {
  items.erase (items.begin () + i);
  nsel -= sel[i];
  sel.erase (sel.begin() + i);
  calc ();
  clamp (0, last, n_1);
}

void item_list::insert (int i, const string& t) {
  if (n && i < n) {
    items.insert (items.begin() + i, t);
    sel.insert (sel.begin()+i, 0);
    calc ();
  }
}

void item_list::set_pos (int x, int y) {
  posx = x;
  posy = y;
  extents.left = posx;
  extents.bottom = posy;
  extents.top = extents.bottom;
  for (int i = 0; i < n; ++i) {
    extents.right = max (extents.right, posx + get_char_width (items[i]));
    extents.top += line_height;
  }
  yt = extents.top - line_height;
  extents.calc ();
}

void item_list::repos (int tx, int ty) {
  int bt = ty - n * line_height;
  set_pos (tx, bt);
}

void item_list::draw () {
  int x = extents.left, y = yt;
  for (int i = 0; i < n; ++i) {
    if (i == hov) glColor3f (0, 1, 0);
    else if (sel[i]) glColor3f (0, 1, 1);
    else glColor3f (clr.r, clr.g, clr.b);
    int xp = draw_string (items[i], x, y);
    draw_string (nums[i], xp, y);
    y -= line_height;
  }

  /*glBegin (GL_LINE_LOOP);
  glVertex2f (extents.left, extents.bottom);
  glVertex2f (extents.right, extents.bottom);
  glVertex2f (extents.right, extents.bottom);
  glVertex2f (extents.right, extents.top);
  glVertex2f (extents.left, extents.top);
  glEnd ();*/


}

void item_list::select (int w) {
  for (int i = 0; i < n; ++i) sel[i]=w;
  nsel = n * w;
  if (sel_lis) sel_lis->selected (*this, get_first ());
}

void item_list::select (int i, int j) {
  if (i > j) std::swap (i, j);
  nsel -= sel[i];
  for (int k = i, l = j + 1; k < l; ++k) sel[k] = 1;
  last = j;
  nsel += (j - i + 1);
}

void item_list::invert_select () {
  for (int i = 0; i < n; ++i) {
    int& si = sel[i];
    nsel -= si;
    si = !si;
    nsel += si;
  }
  if (sel_lis) sel_lis->selected (*this, get_first ());
}

int item_list::select_these (tokenizer& tz) {
  int m; tz >> m;
  if (m) {
    select (0);
    for (int i = 0, j = 0; i < m; ++i) {
      tz >> j;
      sel[j] = 1;
      ++nsel;
    }
    if (sel_lis) sel_lis->selected (*this, get_first ());
  }
  return m;
}

int item_list::handle_input () {
  int r = button::handle_input ();
  hov = -1;
  if (hover && n) {
    int x = extents.left, yh = extents.top, yl = yh - line_height;
    for (int i = 0; i < n; ++i) {
      if (mousex >= x && (mouseyy >= yl && mouseyy <= yh)) {
        hov = i;
        break;
      }
      yh = yl;
      yl -= line_height;
    }
  }
  return r;
}

void item_list::clicked (button& b) {
  if (hov != -1) {
    cur = hov;
    if (shift_down())
      select (last, cur);
    else {
      int& shi = sel[cur];
      nsel -= shi;
      shi = !shi;
      nsel += shi;
      last = cur;
    }
    if (sel_lis) sel_lis->selected (*this, cur);
  }
}

string item_list::get_selected () {
  std::stringstream ss;
  for (int i = 0; i < n; ++i) if (sel[i]) ss << i << SPC;
  return ss.str ();
}

int item_list::get_first () {
  for (int i = 0; i < n; ++i) if (sel[i]) return i;
  return -1;
}