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 + -
显示快捷键?