splitter.cpp
来自「ncbi源码」· C++ 代码 · 共 950 行 · 第 1/2 页
CPP
950 行
int CSplitter::x_GetWidth(int i_x) const{ _ASSERT(i_x >= 0 && i_x <= (int) m_vSplitPosX.size()); int top = (i_x == 0) ? 0 : m_vSplitPosX[i_x - 1] + m_SepSize; int next = (i_x == (int) m_vSplitPosX.size()) ? w() : m_vSplitPosX[i_x]; return next - top;}int CSplitter::x_GetTop(int i_y) const{ _ASSERT(i_y >= 0 && i_y <= (int) m_vSplitPosY.size()); int loc_y = (i_y == 0) ? 0 : (m_vSplitPosY[i_y - 1] + m_SepSize); return y() + loc_y;}int CSplitter::x_GetBottom(int i_y) const{ _ASSERT(i_y >= 0 && i_y <= (int) m_vSplitPosY.size()); int loc_next = (i_y == (int) m_vSplitPosY.size()) ? h() : m_vSplitPosY[i_y]; return y() + loc_next - 1;}int CSplitter::x_GetHeight(int i_y) const{ _ASSERT(i_y >= 0 && i_y <= (int) m_vSplitPosY.size()); int top = (i_y == 0) ? 0 : m_vSplitPosY[i_y - 1] + m_SepSize; int next = (i_y == (int) m_vSplitPosY.size()) ? h() : m_vSplitPosY[i_y]; return next - top;}// removes all child widgets and separatorsvoid CSplitter::x_Clear(){ clear(); m_vSplitPosX.clear(); m_vSplitPosY.clear(); m_vCells.resize(1, NULL); m_vNormSizeX.clear(); m_vNormSizeX.push_back(-1); m_vNormSizeY.clear(); m_vNormSizeY.push_back(-1);}void CSplitter::x_ResizeToCell(int i_cell){ int i_x = x_GetColumn(i_cell); int i_y = x_GetRow(i_cell); x_ResizeToCell(i_x, i_y);}void CSplitter::x_ResizeToCell(int i_x, int i_y){ Fl_Widget* w = x_GetCell(i_x, i_y); if(w) { int left = x_GetLeft(i_x); int width = x_GetWidth(i_x); int top = x_GetTop(i_y); int height = x_GetHeight(i_y); w->resize(left, top, width, height); } }int CSplitter::handle(int event){ m_Event.OnFLTKEvent(event); int res = 0; switch(event) { case FL_KEYDOWN: case FL_KEYUP: res = x_HandleKeyEvent(); break; case FL_MOVE: res = x_HandleMouseMove(); break; case FL_PUSH: res = x_HandleMousePush(); break; case FL_DRAG: res = x_HandleMouseDrag(); break; case FL_RELEASE: res = x_HandleMouseRelease(); break; default: res = Fl_Group::handle(event); } return res;}int CSplitter::x_HandleKeyEvent(){ return 0;}int CSplitter::x_HandleMouseMove(){ int i_sep_x = x_HitTestSeparator(Fl::event_x() - x(), m_vSplitPosX); int i_sep_y = x_HitTestSeparator(Fl::event_y() - y(), m_vSplitPosY); Fl_Cursor cursor = FL_CURSOR_DEFAULT; if(i_sep_x == -1) { cursor = (i_sep_y == -1) ? FL_CURSOR_DEFAULT : FL_CURSOR_NS; } else { cursor = (i_sep_y == -1) ? FL_CURSOR_WE : FL_CURSOR_MOVE ; } fl_cursor(cursor, FL_BLACK, FL_WHITE); if(i_sep_x == -1 && i_sep_y == -1) { return Fl_Group::handle(FL_MOVE); } else return 1;}int CSplitter::x_HandleMousePush(){ switch(m_Event.GetGUISignal()) { case CGUIEvent::ePush: return true; case CGUIEvent::eSelectSignal: { m_MouseDownX = Fl::event_x(); m_MouseDownY = Fl::event_y(); int i_sep_x = x_HitTestSeparator(Fl::event_x() - x(), m_vSplitPosX); int i_sep_y = x_HitTestSeparator(Fl::event_y() - y(), m_vSplitPosY); bool b_hit_x_sep = (i_sep_x != -1); bool b_hit_y_sep = (i_sep_y != -1); int n_clicks = Fl::event_clicks(); if(b_hit_x_sep || b_hit_y_sep) { if(n_clicks == 0) { // single click m_iDragSepX = i_sep_x; m_iDragSepY = i_sep_y; m_StartPosX = (m_iDragSepX == -1) ? -1 : m_vSplitPosX[m_iDragSepX]; m_StartPosY = (m_iDragSepY == -1) ? -1 : m_vSplitPosY[m_iDragSepY]; } else if(n_clicks == 1) { // double click x_DistributeEvenly(b_hit_x_sep, b_hit_y_sep); return 1; } return 1; } return Fl_Group::handle(FL_PUSH); } default: break; }; //switch return Fl_Group::handle(FL_PUSH);}int CSplitter::x_HandleMouseDrag(){ if(x_IsDragging()) { x_DoDragSeparator(false); return 1; } return Fl_Group::handle(FL_DRAG);}int CSplitter::x_HandleMouseRelease(){ bool b_handled = false; if(x_IsDragging()) { // if dragging - do not share events with children x_DoDragSeparator(true); m_iDragSepX = m_iDragSepY = -1; b_handled = true; } else { int i_cell_x, i_cell_y, i_sep_x, i_sep_y; x_HitTest(Fl::event_x() - x(), m_vSplitPosX, i_cell_x, i_sep_x); x_HitTest(Fl::event_y() - y(), m_vSplitPosY, i_cell_y, i_sep_y); if(m_Event.GetGUISignal() == CGUIEvent::ePopupSignal) { if(i_cell_x != -1 && i_cell_y != -1) { // hit the cell b_handled = Fl_Group::handle(FL_RELEASE) != 0; // let the children handle it } if(! b_handled) { // not on child or children haven't handled fl_cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE); x_OnShowPopupMenu(); b_handled = true; } } else Fl_Group::handle(FL_RELEASE); // default handling } return b_handled ? 1 : 0; }void CSplitter::x_DoDragSeparator(bool b_final){ int start_x = 0, stop_x = -1; int start_y = 0, stop_y = -1; if(m_iDragSepX != -1) { int shift = Fl::event_x() - m_MouseDownX; // global shift int new_pos = m_StartPosX + shift; x_MoveSeparator(m_iDragSepX, new_pos, m_vSplitPosX, w(), start_x, stop_x); if(b_final) { m_vNormSizeX[m_iDragSepX] = -1; m_vNormSizeX[m_iDragSepX + 1] = -1; } } if(m_iDragSepY != -1) { int shift = Fl::event_y() - m_MouseDownY; // global shift int new_pos = m_StartPosY + shift; x_MoveSeparator(m_iDragSepY, new_pos, m_vSplitPosY, h(), start_y, stop_y); if(b_final) { m_vNormSizeY[m_iDragSepY] = -1; m_vNormSizeY[m_iDragSepY + 1] = -1; } } x_UpdateRegion(start_x, stop_x, start_y, stop_y); }// z is local coordinate in the dimension corresponding to vposint CSplitter::x_HitTestSeparator(int z, TPosVector& vpos){ int n = vpos.size(); for( int i = 0; i < n; i++ ) { int pos = vpos[i]; if(z >= pos && z < pos + m_SepSize) return i; } return -1;}// assuming that "z" is within splitter boundsvoid CSplitter::x_HitTest(int z, TPosVector& vpos, int& i_cell, int& i_sep){ i_sep = i_cell = -1; int n = vpos.size(); for( int i = 0; i < n; i++ ) { int pos = vpos[i]; if(z < pos) { // belongs to cell i_cell = i; return; } else if(z < pos + m_SepSize) { // belongs to separator i_sep = i; return; } } i_cell = n; return; // belongs to last cell}void CSplitter::x_OnShowPopupMenu(){}void CSplitter::x_DistributeEvenly(bool b_x, bool b_y){ if(b_x) { x_DoDistributeEvenly(m_vSplitPosX, w()); std::fill(m_vNormSizeX.begin(), m_vNormSizeX.end(), -1); } if(b_y) { x_DoDistributeEvenly(m_vSplitPosY, h()); std::fill(m_vNormSizeY.begin(), m_vNormSizeY.end(), -1); } if(b_x || b_y) { for( int i = 0; i < (int) m_vCells.size(); i++ ) { int i_x = x_GetColumn(i); int i_y = x_GetRow(i); x_ResizeToCell(i_x, i_y); } redraw(); }}void CSplitter::x_DoDistributeEvenly(TPosVector& vSplitPos, int size){ int n = vSplitPos.size() + 1; int space = max(0, size - m_SepSize * (n - 1)); int w = space / n; // space per row/column int rest = space - w * n; // space that cannot be divided evenly int pos = w + (rest ? 1 : 0); for( int i = 0; i < n - 1; i++ ) { vSplitPos[i] = pos; pos += w + m_SepSize; if(i < rest) // for first "rest" children add 1 pixel pos++; }}void CSplitter::x_DoResize(TPosVector& v_split_pos, TSizeVector& v_norm_sizes, int size, int new_size){ _ASSERT(v_split_pos.size() + 1 == v_norm_sizes.size()); int n_split = v_split_pos.size(); int min_size = n_split * m_SepSize; if(new_size < size) { // splitter is shrinking int limit = max(new_size, min_size); for( int i = n_split; i >= 0; i--) { int next_start = (i == n_split) ? size : v_split_pos[i]; if(next_start >= limit) { // shrink it int start = (i == 0) ? 0 : (v_split_pos[i - 1] + m_SepSize); if(visible() && v_norm_sizes[i] < 0) { // splitter is visible and cell is being resized for the fisrt time v_norm_sizes[i] = next_start - start; // save original size } if(i < n_split) { v_split_pos[i] = limit; // move separator } limit -= m_SepSize; } else break; } } else if(new_size > size) { // splitter is growing int grow_space = min(new_size - size, size - min_size); int shift = 0; // cumulative shift for split positions for( int i = 0; i < n_split; i++) { if(grow_space > 0 && v_norm_sizes[i] > 0) { // cell needs to grow and there is space left int start = (i == 0) ? 0 : (v_split_pos[i - 1] + m_SepSize); int next_start = + (i == n_split) ? size : v_split_pos[i]; int sz = next_start - start; // current size int new_sz = min(v_norm_sizes[i], sz + grow_space); if(new_sz >= v_norm_sizes[i]) { v_norm_sizes[i] = -1; // does not want to grow anymore } int d_sz = new_sz - sz; // size increase shift += d_sz; grow_space -= d_sz; } if(shift) { v_split_pos[i] += shift; } } }}void CSplitter::x_MoveSeparator(int i_sep, int new_pos, TPosVector& vSplitPos, int size, int& start, int& stop){ _ASSERT(i_sep >= 0 && i_sep < (int) vSplitPos.size()); start = 0; stop = -1; // set empty range int pos = vSplitPos[i_sep]; int d = new_pos - pos; if(d != 0) { int n_sep = vSplitPos.size(); if(d > 0) { // movind down int bottom_lim = size - (n_sep - i_sep) * m_SepSize; new_pos = min(new_pos, bottom_lim); if(new_pos > pos) { // there is space to move to int p = new_pos; int i = i_sep; // move current separator and , if necessary, separator below it for(; i < n_sep; i++) { if(p > vSplitPos[i]) { vSplitPos[i] = p; p += m_SepSize; } else break; } // resize children start = i_sep; stop = min(i, n_sep); } } else if(d < 0) { //moving up int top_lim = i_sep * m_SepSize; new_pos = max(new_pos, top_lim); if(new_pos < pos) { // there is space to move to int p = new_pos; int i = i_sep; // move current separator and , if necessary, separator below it for(; i >= 0; i--) { if(p < vSplitPos[i]) { vSplitPos[i] = p; p -= m_SepSize; } else break; } // resize children start = max(0, i + 1); stop = i_sep + 1; } } }}void CSplitter::x_UpdateRegion(int start_x, int stop_x, int start_y, int stop_y){ bool b_redraw = false; for(int i_x = 0; i_x <= (int) m_vSplitPosX.size(); i_x++ ) { for( int i_y = 0; i_y <= (int) m_vSplitPosY.size(); i_y++ ) { // if cell belongs to one of the affected ranges - resize it if( (i_x >= start_x && i_x <= stop_x) || (i_y >= start_y && i_y <= stop_y) ) { b_redraw = true; x_ResizeToCell(i_x, i_y); } } } if(b_redraw) { redraw(); }}void CSplitter::x_NewSplit(TPosVector& v_split_pos, TSizeVector& v_norm_size, int size){ int n_split = v_split_pos.size(); int sum_size = h() - n_split * m_SepSize; int av_size = sum_size / (n_split + 1); // average cell size // splitting... v_split_pos.push_back(size); v_norm_size.push_back(-1); n_split++; // calculate new sizes double K = (double)(sum_size - m_SepSize) / (sum_size + av_size); TPosVector sizes(n_split); for( int i = 0; i < n_split; i++ ) { int start = (i == 0) ? 0 : v_split_pos[i - 1] + m_SepSize; int size = v_split_pos[i] - start; sizes[i] = (int)( K * size); } // moving split points for( int pos = 0, i = 0; i < n_split; i++ ) { pos += sizes[i]; v_split_pos[i] = pos; pos += m_SepSize; }}END_NCBI_SCOPE/* * =========================================================================== * $Log: splitter.cpp,v $ * Revision 1000.1 2004/06/01 21:09:10 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7 * * Revision 1.7 2004/05/21 22:27:53 gorelenk * Added PCH ncbi_pch.hpp * * Revision 1.6 2004/05/13 17:22:54 yazhuk * Clean-up * * Revision 1.5 2004/05/10 16:25:40 yazhuk * Addressed GCC warnings * * Revision 1.4 2004/02/04 20:02:44 yazhuk * Added Remove(), RemoveAll(), Find() and new overload for Create() * * Revision 1.3 2004/01/28 16:40:28 yazhuk * Major refactoring, bug fixes, added new functions * * Revision 1.2 2004/01/23 00:00:29 ucko * Properly capitalize FL directory for headers. * * Revision 1.1 2004/01/22 16:26:24 yazhuk * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?