00001
00002 #include "vgui_grid_tableau.h"
00003
00004
00005
00006
00007 #include <vcl_iostream.h>
00008 #include <vgui/vgui_macro.h>
00009 #include <vgui/vgui_clear_tableau.h>
00010
00011 bool operator==(vgui_grid_tableau_data const &a,
00012 vgui_grid_tableau_data const &b)
00013 {
00014 return
00015 a.handle == b.handle &&
00016 a.tab_pos == b.tab_pos &&
00017 a.is_default == b.is_default &&
00018 a.time_selected == b.time_selected;
00019 }
00020
00021
00022
00023
00024 void vgui_grid_tableau::init(unsigned initial_cols, unsigned initial_rows)
00025 {
00026 cond_row_add = vgui_event_condition(vgui_key('='), vgui_CTRL);
00027 cond_row_remove = vgui_event_condition(vgui_key('-'), vgui_CTRL);
00028 cond_col_add = vgui_event_condition(vgui_key('='));
00029 cond_col_remove = vgui_event_condition(vgui_key('-'));
00030 cond_flip_fwd = vgui_event_condition(vgui_PAGE_DOWN);
00031 cond_flip_bwd = vgui_event_condition(vgui_PAGE_UP);
00032 cond_select = vgui_event_condition(vgui_LEFT);
00033 cond_deselect = vgui_event_condition(vgui_MIDDLE);
00034
00035 INCREMENT_COLS = 50;
00036 INCREMENT_ROWS = 50;
00037
00038 grid_size_changeable = true;
00039 unique_selected_ = false;
00040
00041 #ifdef DEBUG
00042 vcl_cerr << "vgui_grid_tableau::init: initialising grid with "
00043 << initial_cols << " columns and " << initial_rows << " rows\n";
00044 #endif
00045 nb_cols = initial_cols;
00046 nb_rows = initial_rows;
00047 max_cols = initial_cols + INCREMENT_COLS;
00048 max_rows = initial_rows + INCREMENT_ROWS;
00049 last_selected[0] = last_selected[1] = 0;
00050 default_tab = vgui_clear_tableau_new();
00051
00052 grid_pos = vbl_array_2d<grid_data>(max_cols, max_rows);
00053 for (unsigned i = 0; i < nb_cols; i++)
00054 {
00055 for (unsigned j = 0; j < nb_rows; j++)
00056 {
00057 add_default(i, j);
00058 }
00059 }
00060 }
00061
00062
00063
00064
00065 vgui_grid_tableau::vgui_grid_tableau(vgui_tableau_sptr const& l, vgui_tableau_sptr const& r)
00066 {
00067 init(2, 1);
00068 add_next(l);
00069 add_next(r);
00070 }
00071
00072
00073
00074
00075 vgui_grid_tableau::vgui_grid_tableau(vgui_tableau_sptr const& l, vgui_tableau_sptr const& m, vgui_tableau_sptr const& r)
00076 {
00077 init(3, 1);
00078 add_next(l);
00079 add_next(m);
00080 add_next(r);
00081 }
00082
00083
00084
00085
00086
00087 float vgui_grid_tableau::get_x(unsigned col_pos)
00088 {
00089 if (col_pos < nb_cols)
00090 return col_pos * get_w();
00091 else
00092 {
00093 vgui_macro_warning << "Error in get_x: col_pos = " << col_pos << ", max = " << nb_cols << vcl_endl;
00094 return 0;
00095 }
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 float vgui_grid_tableau::get_y(unsigned row_pos)
00105 {
00106 if (row_pos < nb_rows)
00107 return (nb_rows - row_pos - 1) * get_h();
00108 else
00109 {
00110 vgui_macro_warning << "Error in get_y: row_pos = " << row_pos << ", max = " << nb_rows << vcl_endl;
00111 return 0;
00112 }
00113 }
00114
00115
00116
00117
00118 float vgui_grid_tableau::get_w() { return 1.0f/nb_cols; }
00119
00120
00121
00122
00123 float vgui_grid_tableau::get_h() { return 1.0f/nb_rows; }
00124
00125
00126
00127
00128
00129
00130 void vgui_grid_tableau::add_default(unsigned col_pos, unsigned row_pos)
00131 {
00132 if (col_pos < nb_cols && row_pos < nb_rows)
00133 {
00134 grid_pos(col_pos, row_pos).handle
00135 = this->add(default_tab, get_x(col_pos), get_y(row_pos), get_w(), get_h());
00136 grid_pos(col_pos, row_pos).tab_pos = -1;
00137 grid_pos(col_pos, row_pos).is_default = true;
00138 grid_pos(col_pos, row_pos).time_selected = -1;
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 void vgui_grid_tableau::add_next(vgui_tableau_sptr const& tab, unsigned& col,
00149 unsigned& row)
00150 {
00151 tabs.push_back(tab);
00152
00153 for (unsigned j = 0; j < nb_rows; j++)
00154 {
00155 for (unsigned i = 0; i < nb_cols; i++)
00156 {
00157
00158 if (grid_pos(i,j).is_default)
00159 {
00160 this->remove(grid_pos(i,j).handle);
00161 grid_pos(i,j).handle = this->add(tab, get_x(i), get_y(j), get_w(), get_h());
00162 grid_pos(i,j).tab_pos = tabs.size() - 1;
00163 grid_pos(i,j).is_default = false;
00164 #ifdef DEBUG
00165 vcl_cerr << "vgui_grid_tableau::add_next: adding tableau to col = "<< i <<", row = "<< j << '\n';
00166 #endif
00167 row = j; col = i;
00168 return;
00169 }
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178 if (grid_size_changeable)
00179 {
00180
00181 #ifdef DEBUG
00182 vcl_cerr << "vgui_grid_tableau::add_next: current grid is full, adding another column\n";
00183 #endif
00184 add_column();
00185 unsigned col_pos = nb_cols - 1;
00186 unsigned row_pos = 0;
00187 this->remove(grid_pos(col_pos, row_pos).handle);
00188 grid_pos(col_pos, row_pos).handle
00189 = this->add(tab, get_x(col_pos), get_y(row_pos), get_w(), get_h());
00190 grid_pos(col_pos, row_pos).tab_pos = tabs.size() - 1;
00191 grid_pos(col_pos, row_pos).is_default = false;
00192 #ifdef DEBUG
00193 vcl_cerr << "vgui_grid_tableau::add_next: adding tableau to col = "<< col_pos <<", row = "<< row_pos << '\n';
00194 #endif
00195 row = row_pos; col = col_pos;
00196 }
00197 }
00198
00199 void vgui_grid_tableau::add_next(vgui_tableau_sptr const& tab)
00200 {
00201 unsigned row=0, col = 0;
00202 if (!row&&!col)this->add_next(tab, col, row);
00203 }
00204
00205
00206
00207
00208
00209 void vgui_grid_tableau::add_at(vgui_tableau_sptr const& tab, unsigned col_pos, unsigned row_pos)
00210 {
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 if (col_pos < nb_cols && row_pos < nb_rows)
00222 {
00223 #ifdef DEBUG
00224 vcl_cerr << "vgui_grid_tableau::add_at: adding tableau at col = "<< col_pos <<", row = "<< row_pos << '\n';
00225 #endif
00226 tabs.push_back(tab);
00227 this->remove(grid_pos(col_pos, row_pos).handle);
00228 grid_pos(col_pos, row_pos).handle = this->add(tab, get_x(col_pos), get_y(row_pos), get_w(), get_h());
00229 grid_pos(col_pos, row_pos).tab_pos = tabs.size()-1;
00230 grid_pos(col_pos, row_pos).is_default = false;
00231 layout_grid();
00232 }
00233 else {
00234 vcl_cerr << __FILE__ ": in add_at():\n"
00235 << __FILE__ ": nb_cols nb_rows = " << nb_cols << ' ' << nb_rows << vcl_endl
00236 << __FILE__ ": col_pos row_pos = " << col_pos << ' ' << row_pos << vcl_endl;
00237 }
00238 }
00239
00240
00241
00242
00243
00244 void vgui_grid_tableau::remove_at(unsigned col_pos, unsigned row_pos)
00245 {
00246 #ifdef DEBUG
00247 vcl_cerr << "vgui_grid_tableau::remove_at: removing tableau at col = " << col_pos << ", row = " << row_pos << '\n';
00248 #endif
00249 if (col_pos < nb_cols && row_pos < nb_rows)
00250 {
00251 if (! grid_pos(col_pos, row_pos).is_default)
00252 {
00253 this->remove(grid_pos(col_pos, row_pos).handle);
00254 tabs.erase(tabs.begin() + grid_pos(col_pos, row_pos).tab_pos);
00255 grid_pos(col_pos, row_pos).handle
00256 = this->add(default_tab, get_x(col_pos), get_y(row_pos), get_w(), get_h());
00257 grid_pos(col_pos, row_pos).tab_pos = -1;
00258 grid_pos(col_pos, row_pos).is_default = true;
00259 layout_grid();
00260 }
00261 }
00262 else {
00263 vcl_cerr << __FILE__ ": in remove_at():\n"
00264 << __FILE__ ": nb_cols nb_rows = " << nb_cols << ' ' << nb_rows << vcl_endl
00265 << __FILE__ ": col_pos row_pos = " << col_pos << ' ' << row_pos << vcl_endl;
00266 }
00267 }
00268
00269
00270
00271
00272 vgui_tableau_sptr vgui_grid_tableau::get_tableau_at(unsigned col_pos, unsigned row_pos)
00273 {
00274 if (col_pos < nb_cols && row_pos < nb_rows &&
00275 ! grid_pos(col_pos, row_pos).is_default)
00276 return this->get(grid_pos(col_pos, row_pos).handle);
00277
00278 if (col_pos >= nb_cols)
00279 vgui_macro_warning << "Given column number " << col_pos
00280 << " is out of range, max value = " << nb_cols-1 << vcl_endl;
00281 else if ( row_pos >= nb_rows)
00282 vgui_macro_warning << "Given row number " << row_pos
00283 << " is out of range, max value = " << nb_rows-1 << vcl_endl;
00284 #ifdef DEBUG
00285 else vgui_macro_warning << "Only default tableau at (" << col_pos << ", " << row_pos << ").\n";
00286 #endif
00287 return vgui_tableau_sptr();
00288 }
00289
00290
00291
00292
00293
00294 bool vgui_grid_tableau::cell_bounding_box(unsigned col, unsigned row,
00295 float& xmin, float& ymin,
00296 float& xmax, float& ymax)
00297 {
00298 if (col>=nb_cols || row>=nb_rows)
00299 return false;
00300 vgui_poly_tableau_vp_sc_snapshot snap;
00301 float x0 = snap.vp[0], y0 = snap.vp[1];
00302 float w = snap.vp[2], h = snap.vp[3];
00303 float dx = w/nb_cols, dy = h/nb_rows;
00304 xmin = x0 + col*dx; ymin = y0 + row*dy;
00305 xmax = xmin + dx; ymax = ymin + dy;
00306 return true;
00307 }
00308
00309
00310
00311
00312
00313
00314 void vgui_grid_tableau::get_active_position(unsigned* col_pos, unsigned* row_pos)
00315 {
00316 *col_pos = nb_cols + 1;
00317 *row_pos = nb_rows + 1;
00318 int current_handle;
00319 current_handle = this->get_current_id();
00320
00321 if (current_handle == -1)
00322 {
00323 return;
00324 }
00325
00326 for (unsigned i = 0; i < nb_cols; i++)
00327 {
00328 for (unsigned j = 0; j < nb_rows; j++)
00329 {
00330 if (grid_pos(i,j).handle == current_handle)
00331 {
00332 *col_pos = i;
00333 *row_pos = j;
00334 return;
00335 }
00336 }
00337 }
00338 }
00339
00340
00341
00342
00343 void vgui_grid_tableau::get_last_selected_position(
00344 unsigned* col_pos, unsigned* row_pos)
00345 {
00346 *col_pos = last_selected[0];
00347 *row_pos = last_selected[1];
00348 }
00349
00350
00351
00352
00353 void vgui_grid_tableau::set_selected(int r, int c, bool onoff)
00354 {
00355 int time = onoff ? 1000 : -1;
00356
00357 if ((unsigned int)r < nb_rows && (unsigned int)c < nb_cols) {
00358 grid_pos(c,r).time_selected = time;
00359 } else {
00360 vcl_cerr << "vgui_grid_tableau::set_selected: (r,c) > (cols,rows)\n";
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371 int vgui_grid_tableau::get_selected_positions(vcl_vector<int>* col_pos,
00372 vcl_vector<int>* row_pos,
00373 vcl_vector<int>* times)
00374 {
00375 int nb_selected = 0;
00376 for (unsigned i = 0; i < nb_cols; i++)
00377 {
00378 for (unsigned j = 0; j < nb_rows; j++)
00379 {
00380 if (grid_pos(i,j).time_selected != -1)
00381 {
00382 col_pos->push_back(i);
00383 row_pos->push_back(j);
00384 times->push_back(grid_pos(i,j).time_selected);
00385 nb_selected++;
00386 }
00387 }
00388 }
00389 return nb_selected;
00390 }
00391
00392
00393
00394
00395
00396
00397 void vgui_grid_tableau::layout_grid()
00398 {
00399 #ifdef DEBUG
00400 vcl_cerr << "vgui_grid_tableau::layout_grid: redrawing grid keeping current row and column positions\n";
00401 #endif
00402 for (unsigned i = 0; i < nb_cols; i++)
00403 {
00404 for (unsigned j = 0; j < nb_rows; j++)
00405 {
00406 this->move(grid_pos(i,j).handle, get_x(i), get_y(j), get_w(), get_h());
00407 }
00408 }
00409 }
00410
00411
00412
00413
00414 void vgui_grid_tableau::layout_grid2()
00415 {
00416 #ifdef DEBUG
00417 vcl_cerr << "vgui_grid_tableau::layout_grid2: redrawing grid without gaps\n";
00418 #endif
00419 unsigned grid_col = 0;
00420 unsigned grid_row = 0;
00421 for (unsigned j = 0; j < nb_rows; j++)
00422 {
00423 for (unsigned i = 0; i < nb_cols; i++)
00424 {
00425 this->move(grid_pos(i,j).handle, get_x(grid_col), get_y(grid_row), get_w(), get_h());
00426 grid_pos(grid_col, grid_row).handle = grid_pos(i,j).handle;
00427 grid_pos(grid_col, grid_row).tab_pos = grid_pos(i,j).tab_pos;
00428 if (i != grid_col || j != grid_row)
00429 grid_pos(i,j).handle = -1;
00430 if (grid_col < (nb_cols - 1))
00431 grid_col++;
00432 else
00433 {
00434 grid_row++;
00435 grid_col = 0;
00436 }
00437 }
00438 }
00439 }
00440
00441
00442
00443
00444 void vgui_grid_tableau::add_column()
00445 {
00446 nb_cols++;
00447 #ifdef DEBUG
00448 vcl_cerr << "vgui_grid_tableau::add_column: number of columns is now " << nb_cols << '\n';
00449 #endif
00450
00451 if (nb_cols > max_cols)
00452 {
00453
00454 vcl_cerr << "vgui_grid_tableau::add_column(): Warning: nb_cols > max_cols\n";
00455 }
00456
00457 for (unsigned j = 0; j < nb_rows; j++)
00458 add_default(nb_cols-1, j);
00459
00460 layout_grid();
00461 }
00462
00463
00464
00465
00466 void vgui_grid_tableau::remove_column()
00467 {
00468 if (nb_cols > 1)
00469 {
00470 for (unsigned j = 0; j < nb_rows; j++)
00471 {
00472 this->remove(grid_pos(nb_cols-1, j).handle);
00473 }
00474 nb_cols--;
00475 #ifdef DEBUG
00476 vcl_cerr << "vgui_grid_tableau::remove_column: number of columns is now " << nb_cols << '\n';
00477 #endif
00478 layout_grid();
00479 }
00480 }
00481
00482
00483
00484
00485 void vgui_grid_tableau::add_row()
00486 {
00487 nb_rows++;
00488 #ifdef DEBUG
00489 vcl_cerr << "vgui_grid_tableau::add_row: number of rows is now " << nb_rows << '\n';
00490 #endif
00491 if (nb_rows > max_rows)
00492 {
00493
00494 vcl_cerr << "vgui_grid_tableau::add_row(): Warning: nb_rows > max_rows\n";
00495 }
00496 for (unsigned i = 0; i < nb_cols; i++)
00497 {
00498 add_default(i, nb_rows-1);
00499 }
00500 layout_grid();
00501 }
00502
00503
00504
00505
00506 void vgui_grid_tableau::remove_row()
00507 {
00508 if (nb_rows > 1)
00509 {
00510 for (unsigned i = 0; i < nb_cols; i++)
00511 {
00512 this->remove(grid_pos(i, nb_rows-1).handle);
00513 }
00514 nb_rows--;
00515 #ifdef DEBUG
00516 vcl_cerr << "vgui_grid_tableau::remove_row: number of rows is now " << nb_rows << '\n';
00517 #endif
00518 layout_grid();
00519 }
00520 }
00521
00522
00523
00524
00525 void vgui_grid_tableau::page_up()
00526 {
00527 unsigned row_pos, col_pos;
00528 get_active_position(&col_pos, &row_pos);
00529 #ifdef DEBUG
00530 vcl_cerr << "vgui_grid_tableau::page_up called on col_pos = " << col_pos << ", row_pos = " << row_pos << '\n';
00531 #endif
00532
00533 if (col_pos < nb_cols && row_pos < nb_rows)
00534 {
00535
00536 unsigned tab_index = grid_pos(col_pos, row_pos).tab_pos;
00537
00538 if (tab_index < (tabs.size() - 1) &&
00539 ! grid_pos(col_pos, row_pos).is_default)
00540 {
00541 this->replace(grid_pos(col_pos, row_pos).handle, tabs[tab_index + 1]);
00542 grid_pos(col_pos, row_pos).tab_pos++;
00543 }
00544 else
00545 {
00546 this->replace(grid_pos(col_pos, row_pos).handle, tabs[0]);
00547 grid_pos(col_pos, row_pos).tab_pos = 0;
00548 grid_pos(col_pos, row_pos).is_default = false;
00549 }
00550 }
00551 }
00552
00553
00554
00555
00556 void vgui_grid_tableau::page_down()
00557 {
00558 unsigned row_pos, col_pos;
00559 get_active_position(&col_pos, &row_pos);
00560 #ifdef DEBUG
00561 vcl_cerr << "vgui_grid_tableau::page_down called on col_pos = " << col_pos << ", row_pos = " << row_pos << '\n';
00562 #endif
00563
00564 if (col_pos < nb_cols && row_pos < nb_rows)
00565 {
00566
00567 unsigned tab_index = grid_pos(col_pos, row_pos).tab_pos;
00568
00569 if (tab_index > 0 &&
00570 ! grid_pos(col_pos, row_pos).is_default)
00571 {
00572 this->replace(grid_pos(col_pos, row_pos).handle, tabs[tab_index - 1]);
00573 grid_pos(col_pos, row_pos).tab_pos--;
00574 }
00575 else
00576 {
00577 this->replace(grid_pos(col_pos, row_pos).handle, tabs[tabs.size()-1]);
00578 grid_pos(col_pos, row_pos).tab_pos = tabs.size()-1;
00579 grid_pos(col_pos, row_pos).is_default = false;
00580 }
00581 }
00582 }
00583
00584
00585
00586
00587
00588 void vgui_grid_tableau::select_current(int time)
00589 {
00590 unsigned col, row;
00591 get_active_position(&col, &row);
00592 bool redraw_needed = false;
00593 if (grid_pos(col, row).time_selected == -1)
00594 redraw_needed = true;
00595 grid_pos(col, row).time_selected = time;
00596 last_selected[0] = col;
00597 last_selected[1] = row;
00598 if (redraw_needed)
00599 {
00600 set_outline_color(grid_pos(col,row).handle, 1,0,0);
00601 post_redraw();
00602 }
00603
00604 if (unique_selected_)
00605 {
00606 redraw_needed = false;
00607 for (unsigned r = 0; r<nb_rows; ++r)
00608 for (unsigned c = 0; c<nb_cols; ++c)
00609 if (!(c==col&&r==row))
00610 if (grid_pos(c,r).time_selected != -1)
00611 {
00612 grid_pos(c, r).time_selected = -1;
00613 set_outline_color(grid_pos(c,r).handle, 1,1,1);
00614 redraw_needed = true;
00615 }
00616 if (redraw_needed) post_redraw();
00617 }
00618 }
00619
00620
00621
00622
00623
00624 void vgui_grid_tableau::deselect_current()
00625 {
00626 unsigned col, row;
00627 get_active_position(&col, &row);
00628 if (grid_pos(col,row).time_selected != -1)
00629 {
00630 grid_pos(col, row).time_selected = -1;
00631 set_outline_color(grid_pos(col,row).handle, 1,1,1);
00632 post_redraw();
00633 }
00634 }
00635
00636
00637
00638
00639
00640 bool vgui_grid_tableau::handle(const vgui_event &e)
00641 {
00642 if (cond_row_add(e))
00643 {
00644 add_row();
00645 return true;
00646 }
00647 else if (cond_row_remove(e))
00648 {
00649 remove_row();
00650 return true;
00651 }
00652 else if (cond_col_add(e))
00653 {
00654 add_column();
00655 return true;
00656 }
00657 else if (cond_col_remove(e))
00658 {
00659 remove_column();
00660 return true;
00661 }
00662 else if (cond_flip_fwd(e))
00663 {
00664 page_up();
00665 return true;
00666 }
00667 else if (cond_flip_bwd(e))
00668 {
00669 page_down();
00670 return true;
00671 }
00672 else if (cond_select(e))
00673 {
00674 select_current(e.timestamp);
00675
00676 }
00677 else if (cond_deselect(e))
00678 {
00679 deselect_current();
00680
00681 }
00682
00683
00684 return vgui_poly_tableau::handle(e);
00685 }