splitter.cpp
来自「ncbi源码」· C++ 代码 · 共 950 行 · 第 1/2 页
CPP
950 行
/* * =========================================================================== * PRODUCTION $Log: splitter.cpp,v $ * PRODUCTION Revision 1000.1 2004/06/01 21:09:10 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7 * PRODUCTION * =========================================================================== *//* $Id: splitter.cpp,v 1000.1 2004/06/01 21:09:10 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Andrey Yazhuk * * File Description: * */#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <corelib/ncbistl.hpp>#include <algorithm>#include <gui/widgets/fl/splitter.hpp>#include <FL/fl_draw.H>#include <FL/Fl.H>BEGIN_NCBI_SCOPECSplitter::CSplitter(int x, int y, int w, int h, const char* label) : Fl_Group(x, y, w, h, label), m_Mode(eHorizontal), m_SepSize(4), m_iDragSepX(-1), m_iDragSepY(-1){ Fl_Group::end(); color(fl_rgb_color(224, 224, 224)); box(FL_FLAT_BOX); m_vCells.resize(1, NULL); // by default it has a single cell m_vNormSizeX.resize(1, -1); m_vNormSizeY.resize(1, -1); m_Event.StandardConfig();}CSplitter::~CSplitter(){}CSplitter::EMode CSplitter::GetMode() const{ return m_Mode;}void CSplitter::Create(EMode mode){ if(m_Mode != mode) { x_Clear(); m_Mode = mode; }}const static int kMaxCells = 64;void CSplitter::Create(EMode mode, const TPosVector& sizes){ x_Clear(); switch(mode) { case eHorizontal: x_Create(mode, TPosVector(), sizes); break; case eVertical: x_Create(mode, sizes, TPosVector()); break; case eGrid: x_Create(mode, sizes, sizes); break; };}void CSplitter::Create(EMode mode, const int ar_size[]){ TPosVector sizes; int i = 0; for(; i < kMaxCells; i++ ) { if(ar_size[i] >= 0) sizes.push_back(ar_size[i]); else break; } _ASSERT(i < kMaxCells); Create(mode, sizes);}void CSplitter::Create(EMode mode, const TPosVector& widths, const TPosVector& heights){ x_Create(mode, widths, heights);}void CSplitter::Create(EMode mode, const int ar_w[], const int ar_h[]){ TPosVector widths; int i = 0; for(; i < kMaxCells; i++ ) { if(ar_w[i] >= 0) widths.push_back(ar_w[i]); else break; } _ASSERT(i < kMaxCells); TPosVector heights; for( i = 0; i < kMaxCells; i++ ) { if(ar_h[i] >= 0) heights.push_back(ar_h[i]); else break; } _ASSERT(i < kMaxCells); x_Create(mode, widths, heights);}void CSplitter::Create(int n_horz_panes, int n_vert_panes){ vector<int> widths; vector<int> heights; n_horz_panes = max(1, n_horz_panes); n_vert_panes = max(1, n_vert_panes); for( int i = 0; i < n_horz_panes; i++) widths.push_back(10); for( int i = 0; i < n_vert_panes; i++) heights.push_back(10); EMode mode = (n_horz_panes == 1) ? eVertical : ((n_vert_panes == 1) ? eHorizontal : eGrid); x_Create(mode, widths, heights); x_DistributeEvenly(true, true);}void CSplitter::x_Create(EMode mode, const TPosVector& widths, const TPosVector& heights){ m_Mode = mode; int n_w = widths.size(); int n_h = heights.size(); if(n_w == 0) n_w++; if(n_h == 0) n_h++; _ASSERT(n_w < kMaxCells && n_h < kMaxCells); // keep 'em reasonable x_Clear(); for( int pos = 0, i = 0; i < n_w - 1; i++) { pos += widths[i]; m_vSplitPosX.push_back(pos); } m_vNormSizeX.resize(n_w, -1); for( int pos = 0, i = 0; i < n_h - 1; i++) { pos += heights[i]; m_vSplitPosY.push_back(pos); } m_vNormSizeY.resize(n_h, -1); int n_cells = GetColumnsCount() * GetRowsCount(); m_vCells.resize(n_cells, NULL);}int CSplitter::GetColumnsCount() const{ return m_vSplitPosX.size() + 1;}int CSplitter::GetRowsCount() const{ return m_vSplitPosY.size() + 1;}bool CSplitter::IsValidCell(int i_x, int i_y) const{ return i_x >= 0 && i_x <= (int) m_vSplitPosX.size() && i_y >= 0 && i_y <= (int) m_vSplitPosY.size();}bool CSplitter::InsertToCell(Fl_Widget* w, int i_x, int i_y){ if(i_x >= 0 && i_x < GetColumnsCount() && i_y >= 0 && i_y < GetRowsCount()) { int i_cell = x_GetCellIndex(i_x, i_y); if(m_vCells[i_cell] == NULL) {// cell is vacant int ins_pos = 0; // insertion position for( int i = 0; i < i_cell; i++) { if(m_vCells[i]) ins_pos++; } w->hide(); Fl_Group::insert(*w, ins_pos); m_vCells[i_cell] = w; x_ResizeToCell(i_x, i_y); w->show(); return true; } } return false;} Fl_Widget* CSplitter::RemoveFromCell(int i_x, int i_y){ int i_cell = x_GetCellIndex(i_x, i_y); Fl_Widget* w = m_vCells[i_cell]; if(w) { m_vCells[i_cell] = NULL; Fl_Group::remove(w); } redraw(); return w; }bool CSplitter::Remove(Fl_Widget* w){ int i_x, i_y; if(Find(w, i_x, i_y)) { RemoveFromCell(i_x, i_y); return true; } return false;}void CSplitter::RemoveAll(){ for( size_t i = 0; i < m_vCells.size(); i++ ) { Fl_Widget* w = m_vCells[i]; if(w) { m_vCells[i] = NULL; Fl_Group::remove(w); } } redraw();}bool CSplitter::Find(Fl_Widget* w, int& i_x, int& i_y) const{ i_x = i_y = -1; if(w) { for( int i = 0; i < (int) m_vCells.size(); i++ ) { if(m_vCells[i] == w) { i_x = x_GetColumn(i); i_y = x_GetRow(i); return true; } } } return false;}/// adds a child widget "w" to first vacant cell. If "w" already a child it is/// removed and added again to a new position. If there is no cells available/// new row/column is createdvoid CSplitter::add(Fl_Widget *widget){ TCells::iterator it = std::find(m_vCells.begin(), m_vCells.end(), widget); if(it != m_vCells.end()) { // already a child - remove Fl_Group::remove(*widget); *it = NULL; } // look for first vacant cell it = std::find(m_vCells.begin(), m_vCells.end(), (Fl_Widget*) NULL); if(it != m_vCells.end()) { // there is a vacant cell int i_cell = it - m_vCells.begin(); Fl_Group::insert(*widget, i_cell); m_vCells[i_cell] = widget; int i_x = x_GetColumn(i_cell); int i_y = x_GetRow(i_cell); x_ResizeToCell(i_x, i_y); } else { int old_n_cells = m_vCells.size(); if(m_Mode == eVertical) { x_NewSplit(m_vSplitPosX, m_vNormSizeX, w()); } else { x_NewSplit(m_vSplitPosY, m_vNormSizeY, h()); } Fl_Group::add(widget); m_vCells.resize(GetRowsCount() * GetColumnsCount(), NULL); m_vCells[old_n_cells] = widget; // old_n_cells specifies fisrt vacant position for( int i = 0; i <= old_n_cells; i++ ) { x_ResizeToCell(i); } }}void CSplitter::add(Fl_Widget& w){ CSplitter::add(&w);}void CSplitter::remove(Fl_Widget &w){ TCells::iterator it = std::find(m_vCells.begin(), m_vCells.end(), &w); if(it != m_vCells.end()) { *it = NULL; Fl_Group::remove(w); }}void CSplitter::draw(){ fl_push_clip(x(), y(), w(), h()); if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing: draw_box(); int n_cols = GetColumnsCount(); int n_rows = GetRowsCount(); for( int i_x = 0; i_x < n_cols; i_x++ ) { int left = x_GetLeft(i_x); int right = x_GetRight(i_x); for( int i_y = 0; i_y < n_rows; i_y++ ) { int top = x_GetTop(i_y); int bottom = x_GetBottom(i_y); // horizontal segment draw_box(FL_UP_BOX, left, bottom + 1, right - left + 1, m_SepSize, FL_GRAY); // vertical segment draw_box(FL_UP_BOX, right + 1, top, m_SepSize, bottom - top + 1, FL_GRAY); // intersection draw_box(FL_UP_BOX, right + 1, bottom + 1, m_SepSize, m_SepSize, FL_GRAY); } } } draw_children(); fl_pop_clip();}void CSplitter::resize(int new_x, int new_y, int new_w, int new_h){ bool b_size_changed = new_w != w() || new_h != h(); bool b_pos_changed = new_x != x() || new_y != y(); if(b_size_changed) { x_DoResize(m_vSplitPosX, m_vNormSizeX, w(), new_w); // horizontal x_DoResize(m_vSplitPosY, m_vNormSizeY, h(), new_h); // vertical } if(b_size_changed || b_pos_changed) { Fl_Widget::resize(new_x, new_y, new_w, new_h); for(int i = 0; i < (int) m_vCells.size(); i++ ) { if(m_vCells[i]) x_ResizeToCell(i); } redraw(); }}void CSplitter::init_sizes() { x_Deprecated(); }void CSplitter::insert(Fl_Widget &w, int n) { x_Deprecated(); }void CSplitter::begin() { x_Deprecated(); }void CSplitter::end() { x_Deprecated(); }const Fl_Widget** CSplitter::array() const { x_Deprecated(); return NULL;}Fl_Widget* CSplitter::child(int n) const{ x_Deprecated(); return NULL;}int CSplitter::children() const { x_Deprecated(); return -1; }int CSplitter::find(const Fl_Widget *w) const{ x_Deprecated(); return -1; }int CSplitter::find(const Fl_Widget &w) const{ x_Deprecated(); return -1; }void CSplitter::resizable(Fl_Widget *box) { x_Deprecated(); }void CSplitter::resizable(Fl_Widget &box) { x_Deprecated(); }Fl_Widget* CSplitter::resizable() const{ x_Deprecated(); return NULL;}Fl_Group& CSplitter::add_resizable(Fl_Widget &box){ x_Deprecated(); return *this;}Fl_Widget* CSplitter::x_GetCell(int i_x, int i_y){ bool b_valid = (i_x >= 0 && i_x <= (int) m_vSplitPosX.size()) && (i_y >= 0 && i_y <= (int) m_vSplitPosY.size()); _ASSERT(b_valid); if(b_valid) { int index = i_x + i_y * GetColumnsCount(); return m_vCells[index]; } return NULL;}int CSplitter::x_GetCellIndex(int i_x, int i_y){ bool b_valid = (i_x >= 0 && i_x <= (int) m_vSplitPosX.size()) && (i_y >= 0 && i_y <= (int) m_vSplitPosY.size()); _ASSERT(b_valid); return b_valid ? (i_x + i_y * GetColumnsCount()) : -1;}int CSplitter::x_GetColumn(int i_cell) const{ _ASSERT(i_cell >= 0 && i_cell < (int) m_vCells.size()); int n_cols = m_vSplitPosX.size() + 1; return i_cell % n_cols;}int CSplitter::x_GetRow(int i_cell) const{ _ASSERT(i_cell >= 0 && i_cell < (int) m_vCells.size()); int n_cols = m_vSplitPosX.size() + 1; return i_cell / n_cols;}int CSplitter::x_GetLeft(int i_x) const{ _ASSERT(i_x >= 0 && i_x <= (int) m_vSplitPosX.size()); int loc_x = (i_x == 0) ? 0 : (m_vSplitPosX[i_x - 1] + m_SepSize); return x() + loc_x;}int CSplitter::x_GetRight(int i_x) const{ _ASSERT(i_x >= 0 && i_x <= (int) m_vSplitPosX.size()); int loc_next = (i_x == (int) m_vSplitPosX.size()) ? w() : m_vSplitPosX[i_x]; return x() + loc_next - 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?