sequence_viewer_widget.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:41k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sequence_viewer_widget.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:29:15  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.42
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: sequence_viewer_widget.cpp,v 1000.2 2004/06/01 18:29:15 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Classes to display sequences and alignments with wxWindows front end
  38. *
  39. * ===========================================================================
  40. */
  41. #ifdef _MSC_VER
  42. #pragma warning(disable:4018)   // disable signed/unsigned mismatch warning in MSVC
  43. #endif
  44. #include <ncbi_pch.hpp>
  45. #include <corelib/ncbistd.hpp>
  46. #include "sequence_viewer_widget.hpp"
  47. #include "viewable_alignment.hpp"
  48. #include "cn3d_tools.hpp"
  49. USING_NCBI_SCOPE;
  50. /////////////////////////////////////////////////////////////////////////////////
  51. ///////// These are definitions of the sequence and title drawing areas /////////
  52. /////////////////////////////////////////////////////////////////////////////////
  53. class SequenceViewerWidget_TitleArea : public wxWindow
  54. {
  55. public:
  56.     // constructor (same as wxWindow)
  57.     SequenceViewerWidget_TitleArea(
  58.         wxWindow* parent,
  59.         wxWindowID id = -1,
  60.         const wxPoint& pos = wxDefaultPosition,
  61.         const wxSize& size = wxDefaultSize
  62.     );
  63.     // destructor
  64.     ~SequenceViewerWidget_TitleArea(void);
  65.     void ShowTitles(ViewableAlignment *newAlignment);
  66.     void SetCharacterFont(wxFont *font, int newCellHeight);
  67.     void SetBackgroundColor(const wxColor& backgroundColor);
  68. private:
  69.     void OnPaint(wxPaintEvent& event);
  70.     void OnMouseEvent(wxMouseEvent& event);
  71.     const SequenceViewerWidget_SequenceArea *sequenceArea;
  72.     ViewableAlignment *alignment;
  73.     int highlightedTitleRow;
  74.     wxColor currentBackgroundColor;
  75.     wxFont *titleFont;
  76.     int cellHeight, nTitles, maxTitleWidth;
  77.     DECLARE_EVENT_TABLE()
  78. public:
  79.     int GetMaxTitleWidth(void) const { return maxTitleWidth; }
  80.     void SetSequenceArea(const SequenceViewerWidget_SequenceArea *seqA)
  81.         { sequenceArea = seqA; }
  82. };
  83. class SequenceViewerWidget_SequenceArea : public wxScrolledWindow
  84. {
  85.     friend class SequenceViewerWidget;
  86. public:
  87.     // constructor (same as wxScrolledWindow)
  88.     SequenceViewerWidget_SequenceArea(
  89.         wxWindow* parent,
  90.         wxWindowID id = -1,
  91.         const wxPoint& pos = wxDefaultPosition,
  92.         const wxSize& size = wxDefaultSize,
  93.         long style = wxHSCROLL | wxVSCROLL,
  94.         const wxString& name = "scrolledWindow"
  95.     );
  96.     // destructor
  97.     ~SequenceViewerWidget_SequenceArea(void);
  98.     // stuff from parent widget
  99.     bool AttachAlignment(ViewableAlignment *newAlignment, int initX, int initY);
  100.     void SetMouseMode(SequenceViewerWidget::eMouseMode mode);
  101.     void SetBackgroundColor(const wxColor& backgroundColor);
  102.     void SetCharacterFont(wxFont *font);
  103.     void SetRubberbandColor(const wxColor& rubberbandColor);
  104.     ///// everything else below here is part of the actual implementation /////
  105. private:
  106.     void OnPaint(wxPaintEvent& event);
  107.     void OnMouseEvent(wxMouseEvent& event);
  108.     void OnScrollWin(wxScrollWinEvent& event);
  109.     SequenceViewerWidget_TitleArea *titleArea;
  110.     ViewableAlignment *alignment;
  111.     wxBitmap *bitmap;    // for memoryDC/Blit
  112.     wxFont *currentFont;            // character font
  113.     wxColor currentBackgroundColor; // background for whole window
  114.     wxColor currentRubberbandColor; // color of rubber band
  115.     SequenceViewerWidget::eMouseMode mouseMode;           // mouse mode
  116.     int cellWidth, cellHeight;      // dimensions of cells in pixels
  117.     int areaWidth, areaHeight;      // dimensions of the alignment (virtual area) in cells
  118.     void DrawCell(wxDC& dc, int x, int y, int vsX, int vsY, bool redrawBackground); // draw a single cell
  119.     enum eRubberbandType {
  120.         eSolid,
  121.         eDot
  122.     };
  123.     eRubberbandType currentRubberbandType;
  124.     void DrawLine(wxDC& dc, int x1, int y1, int x2, int y2);
  125.     void DrawRubberband(wxDC& dc,                           // draw rubber band around cells
  126.         int fromX, int fromY, int toX, int toY, int vsX, int vsY);
  127.     void MoveRubberband(wxDC &dc, int fromX, int fromY,     // change rubber band
  128.         int prevToX, int prevToY, int toX, int toY, int vsX, int vsY);
  129.     void RemoveRubberband(wxDC& dc, int fromX, int fromY,   // remove rubber band
  130.         int toX, int toY, int vsX, int vsY);
  131.     DECLARE_EVENT_TABLE()
  132. public:
  133.     int GetCellHeight(void) const { return cellHeight; }
  134.     int GetAreaHeight(void) const { return areaHeight; }
  135.     void SetTitleArea(SequenceViewerWidget_TitleArea *titleA)
  136.         { titleArea = titleA; }
  137.     SequenceViewerWidget::eMouseMode GetMouseMode(void) const { return mouseMode; }
  138. };
  139. ///////////////////////////////////////////////////////////////////////////
  140. ///////// This is the implementation of the sequence drawing area /////////
  141. ///////////////////////////////////////////////////////////////////////////
  142. BEGIN_EVENT_TABLE(SequenceViewerWidget_SequenceArea, wxScrolledWindow)
  143.     EVT_PAINT               (SequenceViewerWidget_SequenceArea::OnPaint)
  144.     EVT_MOUSE_EVENTS        (SequenceViewerWidget_SequenceArea::OnMouseEvent)
  145.     EVT_SCROLLWIN           (SequenceViewerWidget_SequenceArea::OnScrollWin)
  146. END_EVENT_TABLE()
  147. SequenceViewerWidget_SequenceArea::SequenceViewerWidget_SequenceArea(
  148.         wxWindow* parent,
  149.         wxWindowID id,
  150.         const wxPoint& pos,
  151.         const wxSize& size,
  152.         long style,
  153.         const wxString& name
  154.     ) :
  155.     wxScrolledWindow(parent, -1, pos, size, style, name),
  156.     alignment(NULL), currentFont(NULL), titleArea(NULL), bitmap(NULL)
  157. {
  158.     // set default background color
  159.     currentBackgroundColor = *wxWHITE;
  160.     // set default mouse mode
  161.     mouseMode = SequenceViewerWidget::eSelectRectangle;
  162.     // set default rubber band color
  163.     currentRubberbandColor = *wxRED;
  164. }
  165. SequenceViewerWidget_SequenceArea::~SequenceViewerWidget_SequenceArea(void)
  166. {
  167.     if (currentFont) delete currentFont;
  168.     if (bitmap) delete bitmap;
  169. }
  170. bool SequenceViewerWidget_SequenceArea::AttachAlignment(
  171.     ViewableAlignment *newAlignment, int initX, int initY)
  172. {
  173.     alignment = newAlignment;
  174.     if (alignment) {
  175.         // set size of virtual area
  176.         alignment->GetSize(&areaWidth, &areaHeight);
  177.         if (areaWidth <= 0 || areaHeight <= 0) return false;
  178. //        TESTMSG(Info << "area height " << areaHeight);
  179.         // "+1" to make sure last real column and row are always visible, even
  180.         // if visible area isn't exact multiple of cell size
  181.         SetScrollbars(
  182.             cellWidth, cellHeight,
  183.             areaWidth + 1, areaHeight + 1,
  184.             initX, initY);
  185.         alignment->MouseOver(-1, -1);
  186.     } else {
  187.         // remove scrollbars
  188. //        areaWidth = areaHeight = 2;
  189. //        SetScrollbars(10, 10, 2, 2, 0, 0);   //can't do this without crash on win98... ?
  190.     }
  191.     return true;
  192. }
  193. void SequenceViewerWidget_SequenceArea::SetBackgroundColor(const wxColor& backgroundColor)
  194. {
  195.     currentBackgroundColor = backgroundColor;
  196. }
  197. void SequenceViewerWidget_SequenceArea::SetCharacterFont(wxFont *font)
  198. {
  199.     if (!font) return;
  200.     wxClientDC dc(this);
  201.     dc.SetFont(wxNullFont);
  202.     if (currentFont) delete currentFont;
  203.     currentFont = font;
  204.     dc.SetFont(*currentFont);
  205.     wxCoord chW, chH;
  206.     dc.SetMapMode(wxMM_TEXT);
  207.     dc.GetTextExtent("A", &chW, &chH);
  208.     cellWidth = chW + 1;
  209. cellHeight = chH;
  210.     // need to reset scrollbars and virtual area size
  211.     AttachAlignment(alignment, 0, 0);
  212. }
  213. void SequenceViewerWidget_SequenceArea::SetMouseMode(SequenceViewerWidget::eMouseMode mode)
  214. {
  215.     mouseMode = mode;
  216. }
  217. void SequenceViewerWidget_SequenceArea::SetRubberbandColor(const wxColor& rubberbandColor)
  218. {
  219.     currentRubberbandColor = rubberbandColor;
  220. }
  221. void SequenceViewerWidget_SequenceArea::OnPaint(wxPaintEvent& event)
  222. {
  223.     // adjust bitmap size to match client area size
  224.     if (!bitmap || bitmap->GetWidth() != GetClientSize().GetWidth() ||
  225.                    bitmap->GetHeight() != GetClientSize().GetHeight()) {
  226.         if (bitmap) delete bitmap;
  227.         bitmap = new wxBitmap(GetClientSize().GetWidth(), GetClientSize().GetHeight());
  228.     }
  229.     wxMemoryDC memDC;
  230.     memDC.SelectObject(*bitmap);
  231.     int vsX, vsY,
  232.         updLeft, updRight, updTop, updBottom,
  233.         firstCellX, firstCellY,
  234.         lastCellX, lastCellY,
  235.         x, y;
  236.     static int prevVsY = -1;
  237.     memDC.BeginDrawing();
  238.     // set font for characters
  239.     if (alignment) {
  240.         memDC.SetFont(*currentFont);
  241.         memDC.SetMapMode(wxMM_TEXT);
  242.         // characters to be drawn transparently over background
  243.         memDC.SetBackgroundMode(wxTRANSPARENT);
  244.         // get upper left corner of visible area
  245.         GetViewStart(&vsX, &vsY);  // returns coordinates in scroll units (cells)
  246. //        TRACEMSG("vsX=" << vsX << " vsY=" << vsY);
  247.         if (vsY != prevVsY) {
  248.             if (titleArea) titleArea->Refresh();
  249.             prevVsY = vsY;
  250.         }
  251.     }
  252.     // get the update rect list, so that we can draw *only* the cells
  253.     // in the part of the window that needs redrawing; update region
  254.     // coordinates are relative to the visible part of the drawing area
  255.     wxRegionIterator upd(GetUpdateRegion());
  256.     for (; upd; ++upd) {
  257. //        TRACEMSG("upd: x=" << upd.GetX() << " y=" << upd.GetY() <<
  258. //            " w=" << upd.GetW() << " h=" << upd.GetH());
  259.         // draw background
  260.         memDC.SetPen(*(wxThePenList->
  261.             FindOrCreatePen(currentBackgroundColor, 1, wxSOLID)));
  262.         memDC.SetBrush(*(wxTheBrushList->
  263.             FindOrCreateBrush(currentBackgroundColor, wxSOLID)));
  264.         memDC.DrawRectangle(upd.GetX(), upd.GetY(), upd.GetW(), upd.GetH());
  265.         if (!alignment) continue;
  266.         // figure out which cells contain the corners of the update region
  267.         // get coordinates of update region corners relative to virtual area
  268.         updLeft = vsX*cellWidth + upd.GetX();
  269.         updTop = vsY*cellHeight + upd.GetY();
  270.         updRight = updLeft + upd.GetW() - 1;
  271.         updBottom = updTop + upd.GetH() - 1;
  272.         // firstCell[X,Y] is upper leftmost cell to draw, and is the cell
  273.         // that contains the upper left corner of the update region
  274.         firstCellX = updLeft / cellWidth;
  275.         firstCellY = updTop / cellHeight;
  276.         // lastCell[X,Y] is the lower rightmost cell displayed; including partial
  277.         // cells if the visible area isn't an exact multiple of cell size. (It
  278.         // turns out to be very difficult to only display complete cells...)
  279.         lastCellX = updRight / cellWidth;
  280.         lastCellY = updBottom / cellHeight;
  281.         // restrict to size of virtual area, if visible area is larger
  282.         // than the virtual area
  283.         if (lastCellX >= areaWidth) lastCellX = areaWidth - 1;
  284.         if (lastCellY >= areaHeight) lastCellY = areaHeight - 1;
  285.         // draw cells
  286. //        TESTMSG("drawing cells " << firstCellX << ',' << firstCellY
  287. //            << " to " << lastCellX << ',' << lastCellY);
  288.         for (y=firstCellY; y<=lastCellY; ++y) {
  289.             for (x=firstCellX; x<=lastCellX; ++x) {
  290.                 DrawCell(memDC, x, y, vsX, vsY, false);
  291.             }
  292.         }
  293.     }
  294.     memDC.EndDrawing();
  295.     // Blit from memory DC to paintDC to avoid flicker
  296.     wxPaintDC paintDC(this);
  297.     paintDC.Blit(0, 0, GetClientSize().GetWidth(), GetClientSize().GetHeight(), &memDC, 0,0, wxCOPY);
  298. //    TRACEMSG("Blit 0, 0, " << GetClientSize().GetWidth() << ", " << GetClientSize().GetHeight());
  299. }
  300. void SequenceViewerWidget_SequenceArea::DrawCell(wxDC& dc, int x, int y, int vsX, int vsY, bool redrawBackground)
  301. {
  302. char character;
  303.     wxColor color, cellBackgroundColor;
  304.     bool drawBackground, drawChar;
  305.     drawChar = alignment->GetCharacterTraitsAt(x, y, &character, &color, &drawBackground, &cellBackgroundColor);
  306.     // adjust x,y into visible area coordinates
  307.     x = (x - vsX) * cellWidth;
  308.     y = (y - vsY) * cellHeight;
  309.     // if necessary, redraw background with appropriate color
  310.     if ((drawChar && drawBackground) || redrawBackground) {
  311.         if (drawChar && drawBackground) {
  312.             dc.SetPen(*(wxThePenList->FindOrCreatePen(cellBackgroundColor, 1, wxSOLID)));
  313.             dc.SetBrush(*(wxTheBrushList->FindOrCreateBrush(cellBackgroundColor, wxSOLID)));
  314.         } else {
  315.             dc.SetPen(*(wxThePenList->FindOrCreatePen(currentBackgroundColor, 1, wxSOLID)));
  316.             dc.SetBrush(*(wxTheBrushList->FindOrCreateBrush(currentBackgroundColor, wxSOLID)));
  317.         }
  318.         dc.DrawRectangle(x, y, cellWidth, cellHeight);
  319.     }
  320.     if (!drawChar) return;
  321.     // set character color
  322.     dc.SetTextForeground(color);
  323.     // measure character size
  324.     wxString buf(character);
  325.     wxCoord chW, chH;
  326.     dc.GetTextExtent(buf, &chW, &chH);
  327.     // draw character in the middle of the cell
  328.     dc.DrawText(buf,
  329.         x + (cellWidth - chW)/2,
  330.         y + (cellHeight - chH)/2
  331.     );
  332. }
  333. static inline void min_max(int a, int b, int *c, int *d)
  334. {
  335.     if (a <= b) {
  336.         *c = a;
  337.         *d = b;
  338.     } else {
  339.         *c = b;
  340.         *d = a;
  341.     }
  342. }
  343. void SequenceViewerWidget_SequenceArea::DrawLine(wxDC& dc, int x1, int y1, int x2, int y2)
  344. {
  345.     if (currentRubberbandType == eSolid) {
  346.         dc.DrawLine(x1, y1, x2, y2);
  347.     } else { // short-dashed line
  348.         int i, ie;
  349.         if (x1 == x2) { // vertical line
  350.             min_max(y1, y2, &i, &ie);
  351.             ie -= 1;
  352.             for (; i<=ie; ++i)
  353.                 if (i%4 == 0) dc.DrawLine(x1, i, x1, i + 2);
  354.         } else {        // horizontal line
  355.             min_max(x1, x2, &i, &ie);
  356.             ie -= 1;
  357.             for (; i<=ie; ++i)
  358.                 if (i%4 == 0) dc.DrawLine(i, y1, i + 2, y1);
  359.         }
  360.     }
  361. }
  362. // draw a rubberband around the cells
  363. void SequenceViewerWidget_SequenceArea::DrawRubberband(wxDC& dc, int fromX, int fromY, int toX, int toY, int vsX, int vsY)
  364. {
  365.     // find upper-left and lower-right corners
  366.     int minX, minY, maxX, maxY;
  367.     min_max(fromX, toX, &minX, &maxX);
  368.     min_max(fromY, toY, &minY, &maxY);
  369.     // convert to pixel coordinates of corners
  370.     minX = (minX - vsX) * cellWidth;
  371.     minY = (minY - vsY) * cellHeight;
  372.     maxX = (maxX - vsX) * cellWidth + cellWidth - 1;
  373.     maxY = (maxY - vsY) * cellHeight + cellHeight - 1;
  374.     // set color
  375.     dc.SetPen(*(wxThePenList->FindOrCreatePen(currentRubberbandColor, 1, wxSOLID)));
  376.     // draw sides (should draw in order, due to pixel roundoff)
  377.     if (mouseMode != SequenceViewerWidget::eSelectColumns)
  378.         DrawLine(dc, minX, minY, maxX, minY);   // top
  379.     if (mouseMode != SequenceViewerWidget::eSelectRows)
  380.         DrawLine(dc, maxX, minY, maxX, maxY);   // right
  381.     if (mouseMode != SequenceViewerWidget::eSelectColumns)
  382.         DrawLine(dc, maxX, maxY, minX, maxY);   // bottom
  383.     if (mouseMode != SequenceViewerWidget::eSelectRows)
  384.         DrawLine(dc, minX, maxY, minX, minY);   // left
  385. }
  386. // move the rubber band to a new rectangle, erasing only the side(s) of the
  387. // rectangle that is changing
  388. void SequenceViewerWidget_SequenceArea::MoveRubberband(wxDC &dc, int fromX, int fromY,
  389.     int prevToX, int prevToY, int toX, int toY, int vsX, int vsY)
  390. {
  391.     int i;
  392.     if ((prevToX >= fromX && toX < fromX) ||
  393.         (prevToX < fromX && toX >= fromX) ||
  394.         (prevToY >= fromY && toY < fromY) ||
  395.         (prevToY < fromY && toY >= fromY)) {
  396.         // need to completely redraw if rectangle is "flipped"
  397.         RemoveRubberband(dc, fromX, fromY, prevToX, prevToY, vsX, vsY);
  398.     } else {
  399.         int a, b;
  400.         // erase moving bottom/top side if dragging up/down
  401.         if (toY != prevToY) {
  402.             min_max(fromX, prevToX, &a, &b);
  403.             for (i=a; i<=b; ++i) DrawCell(dc, i, prevToY, vsX, vsY, true);
  404.         }
  405.         // erase partial top and bottom if dragging left by more than one
  406.         a = -1; b = -2;
  407.         if (fromX <= toX && toX < prevToX) {
  408.             a = toX + 1;
  409.             b = prevToX - 1;
  410.         } else if (prevToX < toX && toX < fromX) {
  411.             a = prevToX + 1;
  412.             b = toX - 1;
  413.         }
  414.         for (i=a; i<=b; ++i) {
  415.             DrawCell(dc, i, fromY, vsX, vsY, true);
  416.             DrawCell(dc, i, prevToY, vsX, vsY, true);
  417.         }
  418.         // erase moving left/right side
  419.         if (toX != prevToX) {
  420.             min_max(fromY, prevToY, &a, &b);
  421.             for (i=a; i<=b; ++i) DrawCell(dc, prevToX, i, vsX, vsY, true);
  422.         }
  423.         // erase partial left and right sides if dragging up/down by more than one
  424.         a = -1; b = -2;
  425.         if (fromY <= toY && toY < prevToY) {
  426.             a = toY + 1;
  427.             b = prevToY - 1;
  428.         } else if (prevToY < toY && toY < fromY) {
  429.             a = prevToY + 1;
  430.             b = toY - 1;
  431.         }
  432.         for (i=a; i<=b; ++i) {
  433.             DrawCell(dc, fromX, i, vsX, vsY, true);
  434.             DrawCell(dc, prevToX, i, vsX, vsY, true);
  435.         }
  436.     }
  437.     // redraw whole new one
  438.     DrawRubberband(dc, fromX, fromY, toX, toY, vsX, vsY);
  439. }
  440. // redraw only those cells necessary to remove rubber band
  441. void SequenceViewerWidget_SequenceArea::RemoveRubberband(wxDC& dc, int fromX, int fromY, int toX, int toY, int vsX, int vsY)
  442. {
  443.     int i, min, max;
  444.     // remove top and bottom
  445.     min_max(fromX, toX, &min, &max);
  446.     for (i=min; i<=max; ++i) {
  447.         DrawCell(dc, i, fromY, vsX, vsY, true);
  448.         DrawCell(dc, i, toY, vsX, vsY, true);
  449.     }
  450.     // remove left and right
  451.     min_max(fromY, toY, &min, &max);
  452.     for (i=min+1; i<=max-1; ++i) {
  453.         DrawCell(dc, fromX, i, vsX, vsY, true);
  454.         DrawCell(dc, toX, i, vsX, vsY, true);
  455.     }
  456. }
  457. void SequenceViewerWidget_SequenceArea::OnScrollWin(wxScrollWinEvent& event)
  458. {
  459.     // when scrolling happens via scrollbars (or movement keys), need to update status bar info.
  460.     // So, fake a (non-moving) mouse wheel event, which will trigger MouseOver.
  461.     wxMouseEvent fake(wxEVT_MOUSEWHEEL);
  462.     fake.m_wheelRotation = 0;
  463.     fake.m_wheelDelta = 120;
  464.     fake.m_linesPerAction = 3;
  465.     AddPendingEvent(fake);
  466.     event.Skip();   // continue to process this event normally
  467. }
  468. void SequenceViewerWidget_SequenceArea::OnMouseEvent(wxMouseEvent& event)
  469. {
  470.     static const ViewableAlignment *prevAlignment = NULL;
  471.     static int prevMOX = -1, prevMOY = -1;
  472.     static bool dragging = false;
  473.     if (!alignment) {
  474.         prevAlignment = NULL;
  475.         prevMOX = prevMOY = -1;
  476.         dragging = false;
  477.         return;
  478.     }
  479.     if (alignment != prevAlignment) {
  480.         prevMOX = prevMOY = -1;
  481.         prevAlignment = alignment;
  482.         dragging = false;
  483.     }
  484.     // get coordinates of mouse when it's over the drawing area
  485.     wxCoord mX, mY;
  486.     event.GetPosition(&mX, &mY);
  487.     // get current view window location
  488.     int vsX, vsY;
  489.     GetViewStart(&vsX, &vsY);
  490.     // handle wheel events
  491.     static wxCoord windowMX = 0, windowMY = 0;
  492.     bool wheelEvent = (event.GetEventType() == wxEVT_MOUSEWHEEL);
  493.     if (wheelEvent) {
  494.         if (dragging || windowMX < 0 || windowMY < 0 ||
  495.                 windowMX >= GetClientSize().GetWidth() || windowMY >= GetClientSize().GetHeight())
  496.             return;
  497.         mX = windowMX;  // coords on mouse wheel event seem to be screen-relative, not window-relative
  498.         mY = windowMY;
  499.         static int accumulatedRotation = 0;
  500.         accumulatedRotation -= event.GetWheelRotation();    // move wheel up -> scroll up
  501.         int nDeltas = accumulatedRotation / event.GetWheelDelta();
  502.         if (nDeltas != 0) {
  503.             accumulatedRotation -= nDeltas * event.GetWheelDelta();
  504.             int toY = vsY + nDeltas * event.GetLinesPerAction();
  505.             if (toY < 0)
  506.                 toY = 0;
  507.             else if (toY >= areaHeight)
  508.                 toY = areaHeight - 1;
  509.             Scroll(-1, toY);
  510.             GetViewStart(&vsX, &vsY);   // update vsY so that MouseOver is called on new position
  511.         }
  512.     } else {
  513.         windowMX = mX;
  514.         windowMY = mY;
  515.     }
  516.     // translate visible area coordinates to cell coordinates
  517.     int cellX, cellY, MOX, MOY;
  518.     cellX = MOX = vsX + mX / cellWidth;
  519.     cellY = MOY = vsY + mY / cellHeight;
  520.     // if the mouse is leaving the window, use cell coordinates of most
  521.     // recent known mouse-over cell
  522.     if (event.Leaving()) {
  523.         cellX = prevMOX;
  524.         cellY = prevMOY;
  525.         MOX = MOY = -1;
  526.     }
  527.     // do MouseOver if not in the same cell (or outside area) as last time
  528.     if (MOX >= areaWidth || MOY >= areaHeight)
  529.         MOX = MOY = -1;
  530.     if (MOX != prevMOX || MOY != prevMOY)
  531.         alignment->MouseOver(MOX, MOY);
  532.     prevMOX = MOX;
  533.     prevMOY = MOY;
  534.     if (wheelEvent)
  535.         return;
  536.     // adjust for column/row selection
  537.     if (mouseMode == SequenceViewerWidget::eSelectColumns)
  538.         cellY = vsY + GetClientSize().GetHeight() / cellHeight;
  539.     else if (mouseMode == SequenceViewerWidget::eSelectRows)
  540.         cellX = vsX + GetClientSize().GetWidth() / cellWidth;
  541.     // limit coordinates of selection to virtual area
  542.     if (cellX < 0) cellX = 0;
  543.     else if (cellX >= areaWidth) cellX = areaWidth - 1;
  544.     if (cellY < 0) cellY = 0;
  545.     else if (cellY >= areaHeight) cellY = areaHeight - 1;
  546.     // keep track of position of selection start, as well as last
  547.     // cell dragged to during selection
  548.     static int fromX, fromY, prevToX, prevToY;
  549.     // limit dragging movement if necessary
  550.     if (dragging) {
  551.         if (mouseMode == SequenceViewerWidget::eDragHorizontal) cellY = fromY;
  552.         if (mouseMode == SequenceViewerWidget::eDragVertical) cellX = fromX;
  553.     }
  554.     // process beginning of selection
  555.     if (event.LeftDown()) {
  556.         // find out which (if any) control keys are down at this time
  557.         unsigned int controls = 0;
  558.         if (event.ShiftDown()) controls |= ViewableAlignment::eShiftDown;
  559. #ifdef __WXMAC__
  560.         if (event.MetaDown())      // control key + mouse doesn't work on Mac?
  561. #else
  562.         if (event.ControlDown())
  563. #endif
  564.             controls |= ViewableAlignment::eControlDown;
  565.         if (event.AltDown() || event.MetaDown()) controls |= ViewableAlignment::eAltOrMetaDown;
  566.         // send MouseDown message; don't start selection if MouseDown returns false
  567.         // or if not inside display area
  568.         if (alignment->MouseDown(MOX, MOY, controls) && MOX != -1) {
  569.             prevToX = fromX = cellX;
  570.             prevToY = fromY = cellY;
  571.             dragging = true;
  572.             TRACEMSG("drawing initial rubberband");
  573.             wxClientDC dc(this);
  574.             dc.BeginDrawing();
  575.             currentRubberbandType =
  576.                 (mouseMode == SequenceViewerWidget::eSelectRectangle ||
  577.                  mouseMode == SequenceViewerWidget::eSelectColumns ||
  578.                  mouseMode == SequenceViewerWidget::eSelectRows) ? eDot : eSolid;
  579.             if (mouseMode == SequenceViewerWidget::eSelectColumns) {
  580.                 fromY = vsY;
  581.                 prevToY = cellY;
  582.                 DrawRubberband(dc, fromX, fromY, fromX, cellY, vsX, vsY);
  583.             } else if (mouseMode == SequenceViewerWidget::eSelectRows) {
  584.                 fromX = vsX;
  585.                 prevToX = cellX;
  586.                 DrawRubberband(dc, fromX, fromY, cellX, fromY, vsX, vsY);
  587.             } else {
  588.                 DrawRubberband(dc, fromX, fromY, fromX, fromY, vsX, vsY);
  589.             }
  590.             dc.EndDrawing();
  591.         }
  592.     }
  593.     // process end of selection, on mouse-up, or if the mouse leaves the window
  594.     else if (dragging && (event.LeftUp() || event.Leaving() || event.Entering())) {
  595.         if (!event.LeftUp()) {
  596.             cellX = prevToX;
  597.             cellY = prevToY;
  598.         }
  599.         dragging = false;
  600.         wxClientDC dc(this);
  601.         dc.BeginDrawing();
  602.         dc.SetFont(*currentFont);
  603.         // remove rubberband
  604.         if (mouseMode == SequenceViewerWidget::eSelectRectangle ||
  605.             mouseMode == SequenceViewerWidget::eSelectColumns ||
  606.             mouseMode == SequenceViewerWidget::eSelectRows)
  607.             RemoveRubberband(dc, fromX, fromY, cellX, cellY, vsX, vsY);
  608.         else {
  609.             DrawCell(dc, fromX, fromY, vsX, vsY, true);
  610.             if (cellX != fromX || cellY != fromY)
  611.                 DrawCell(dc, cellX, cellY, vsX, vsY, true);
  612.         }
  613.         dc.EndDrawing();
  614.         // adjust for column/row selection
  615.         if (mouseMode == SequenceViewerWidget::eSelectColumns) {
  616.             fromY = 0;
  617.             cellY = areaHeight - 1;
  618.         } else if (mouseMode == SequenceViewerWidget::eSelectRows) {
  619.             fromX = 0;
  620.             cellX = areaWidth - 1;
  621.         }
  622.         // do appropriate callback
  623.         if (mouseMode == SequenceViewerWidget::eSelectRectangle ||
  624.             mouseMode == SequenceViewerWidget::eSelectColumns ||
  625.             mouseMode == SequenceViewerWidget::eSelectRows)
  626.             alignment->SelectedRectangle(
  627.                 (fromX < cellX) ? fromX : cellX,
  628.                 (fromY < cellY) ? fromY : cellY,
  629.                 (cellX > fromX) ? cellX : fromX,
  630.                 (cellY > fromY) ? cellY : fromY);
  631.         else
  632.             alignment->DraggedCell(fromX, fromY, cellX, cellY);
  633.     }
  634.     // process continuation of selection - redraw rectangle
  635.     else if (dragging && (cellX != prevToX || cellY != prevToY)) {
  636.         wxClientDC dc(this);
  637.         dc.BeginDrawing();
  638.         dc.SetFont(*currentFont);
  639.         currentRubberbandType = eDot;
  640.         if (mouseMode == SequenceViewerWidget::eSelectRectangle ||
  641.             mouseMode == SequenceViewerWidget::eSelectColumns ||
  642.             mouseMode == SequenceViewerWidget::eSelectRows) {
  643.             MoveRubberband(dc, fromX, fromY, prevToX, prevToY, cellX, cellY, vsX, vsY);
  644.         } else {
  645.             if (prevToX != fromX || prevToY != fromY)
  646.                 DrawCell(dc, prevToX, prevToY, vsX, vsY, true);
  647.             if (cellX != fromX || cellY != fromY) {
  648.                 DrawRubberband(dc, cellX, cellY, cellX, cellY, vsX, vsY);
  649.             }
  650.         }
  651.         dc.EndDrawing();
  652.         prevToX = cellX;
  653.         prevToY = cellY;
  654.     }
  655. }
  656. ////////////////////////////////////////////////////////////////////////
  657. ///////// This is the implementation of the title drawing area /////////
  658. ////////////////////////////////////////////////////////////////////////
  659. BEGIN_EVENT_TABLE(SequenceViewerWidget_TitleArea, wxWindow)
  660.     EVT_PAINT               (SequenceViewerWidget_TitleArea::OnPaint)
  661.     EVT_MOUSE_EVENTS        (SequenceViewerWidget_TitleArea::OnMouseEvent)
  662. END_EVENT_TABLE()
  663. SequenceViewerWidget_TitleArea::SequenceViewerWidget_TitleArea(
  664.         wxWindow* parent,
  665.         wxWindowID id,
  666.         const wxPoint& pos,
  667.         const wxSize& size) :
  668.     wxWindow(parent, id, pos, size, wxNO_3D),
  669.     titleFont(NULL), cellHeight(0), maxTitleWidth(20), alignment(NULL),
  670.     sequenceArea(NULL), highlightedTitleRow(-1)
  671. {
  672.     currentBackgroundColor = *wxWHITE;
  673. }
  674. SequenceViewerWidget_TitleArea::~SequenceViewerWidget_TitleArea(void)
  675. {
  676.     if (titleFont) delete titleFont;
  677. }
  678. void SequenceViewerWidget_TitleArea::ShowTitles(ViewableAlignment *newAlignment)
  679. {
  680.     alignment = newAlignment;
  681.     highlightedTitleRow = -1;
  682.     if (!alignment) return;
  683.     // set font
  684.     wxClientDC dc(this);
  685.     dc.SetFont(*titleFont);
  686.     dc.SetMapMode(wxMM_TEXT);
  687.     int i;
  688.     wxString title;
  689.     wxColor color;
  690.     wxCoord tW, tH;
  691.     // get maximum width of any title
  692.     alignment->GetSize(&i, &nTitles);
  693.     if (nTitles <= 0) return;
  694.     maxTitleWidth = 20;
  695.     for (i=0; i<nTitles; ++i) {
  696.         if (!alignment->GetRowTitle(i, &title, &color)) continue;
  697.         // measure title size
  698.         dc.GetTextExtent(title, &tW, &tH);
  699.         if (tW > maxTitleWidth) maxTitleWidth = tW;
  700.     }
  701. }
  702. void SequenceViewerWidget_TitleArea::SetCharacterFont(wxFont *font, int newCellHeight)
  703. {
  704.     if (!font) return;
  705.     if (titleFont) delete titleFont;
  706.     titleFont = font;
  707.     cellHeight = newCellHeight;
  708.     ShowTitles(alignment);
  709. }
  710. void SequenceViewerWidget_TitleArea::SetBackgroundColor(const wxColor& backgroundColor)
  711. {
  712.     currentBackgroundColor = backgroundColor;
  713. }
  714. void SequenceViewerWidget_TitleArea::OnPaint(wxPaintEvent& event)
  715. {
  716.     wxPaintDC dc(this);
  717.     int vsX, vsY,
  718.         updTop, updBottom,
  719.         firstRow, lastRow, row;
  720.     dc.BeginDrawing();
  721.     // set font for characters
  722.     if (alignment) {
  723.         dc.SetFont(*titleFont);
  724.         dc.SetMapMode(wxMM_TEXT);
  725.         // characters to be drawn transparently over background
  726.         dc.SetBackgroundMode(wxTRANSPARENT);
  727.         // get upper left corner of visible area
  728.         sequenceArea->GetViewStart(&vsX, &vsY);  // returns coordinates in scroll units (cells)
  729.     }
  730.     // get the update rect list, so that we can draw *only* the cells
  731.     // in the part of the window that needs redrawing; update region
  732.     // coordinates are relative to the visible part of the drawing area
  733.     wxRegionIterator upd(GetUpdateRegion());
  734.     for (; upd; ++upd) {
  735. //        if (upd.GetW() == GetClientSize().GetWidth() &&
  736. //            upd.GetH() == GetClientSize().GetHeight())
  737. //            TESTMSG("repainting whole SequenceViewerWidget_TitleArea");
  738.         // draw background
  739.         dc.SetPen(*(wxThePenList->
  740.             FindOrCreatePen(currentBackgroundColor, 1, wxSOLID)));
  741.         dc.SetBrush(*(wxTheBrushList->
  742.             FindOrCreateBrush(currentBackgroundColor, wxSOLID)));
  743.         dc.DrawRectangle(upd.GetX(), upd.GetY(), upd.GetW(), upd.GetH());
  744.         if (!alignment) continue;
  745.         // figure out which cells contain the corners of the update region
  746.         // get coordinates of update region corners relative to virtual area
  747.         updTop = vsY*cellHeight + upd.GetY();
  748.         updBottom = updTop + upd.GetH() - 1;
  749.         firstRow = updTop / cellHeight;
  750.         lastRow = updBottom / cellHeight;
  751.         // restrict to size of virtual area, if visible area is larger
  752.         // than the virtual area
  753.         if (lastRow >= nTitles) lastRow = nTitles - 1;
  754.         // draw titles
  755.         wxString title;
  756.         wxColor color;
  757.         wxCoord tW, tH;
  758.         for (row=firstRow; row<=lastRow; ++row) {
  759.             if (!alignment->GetRowTitle(row, &title, &color)) continue;
  760.             // set character color
  761.             if (row == highlightedTitleRow)
  762.                 dc.SetTextForeground(*wxRED);
  763.             else
  764.                 dc.SetTextForeground(color);
  765.             // draw title centered vertically in the cell
  766.             dc.GetTextExtent(title, &tW, &tH);
  767.             dc.DrawText(title, 0, cellHeight * (row - vsY) + (cellHeight - tH)/2);
  768.         }
  769.     }
  770.     dc.EndDrawing();
  771. }
  772. void SequenceViewerWidget_TitleArea::OnMouseEvent(wxMouseEvent& event)
  773. {
  774.     static const ViewableAlignment *prevAlignment = NULL;
  775.     static int prevMOY = -1;
  776.     if (!alignment) {
  777.         prevAlignment = NULL;
  778.         prevMOY = -1;
  779.         return;
  780.     }
  781.     if (alignment != prevAlignment) {
  782.         prevMOY = -1;
  783.         prevAlignment = alignment;
  784.     }
  785.     // get coordinates of mouse when it's over the drawing area
  786.     wxCoord mX, mY;
  787.     event.GetPosition(&mX, &mY);
  788.     // translate visible area coordinates to cell coordinates
  789.     int vsX, vsY, MOY;
  790.     sequenceArea->GetViewStart(&vsX, &vsY);
  791.     MOY = vsY + mY / cellHeight;
  792.     // if the mouse is leaving the window or is outside area
  793.     if (event.Leaving() || MOY >= sequenceArea->GetAreaHeight())
  794.         MOY = -1;
  795.     // do MouseOver if not in the same cell as last time
  796.     if (MOY != prevMOY)
  797.         alignment->MouseOver(-1, MOY);
  798.     prevMOY = MOY;
  799.     // process button press
  800.     if (event.LeftDown()) {
  801.         // find out which (if any) control keys are down at this time
  802.         unsigned int controls = 0;
  803.         if (event.ShiftDown()) controls |= ViewableAlignment::eShiftDown;
  804. #ifdef __WXMAC__
  805.         if (event.MetaDown())      // control key + mouse doesn't work on Mac?
  806. #else
  807.         if (event.ControlDown())
  808. #endif
  809.             controls |= ViewableAlignment::eControlDown;
  810.         if (event.AltDown() || event.MetaDown()) controls |= ViewableAlignment::eAltOrMetaDown;
  811.         // send MouseDown message
  812.         alignment->MouseDown(-1, MOY, controls);
  813.         // (temporarily) highlight this title
  814.         highlightedTitleRow = MOY;
  815.         Refresh();
  816.     }
  817. }
  818. //////////////////////////////////////////////////////////////////////
  819. ///////// This is the implementation of SequenceViewerWidget /////////
  820. //////////////////////////////////////////////////////////////////////
  821. SequenceViewerWidget::SequenceViewerWidget(
  822.         wxWindow* parent,
  823.         wxWindowID id,
  824.         const wxPoint& pos,
  825.         const wxSize& size) :
  826.     wxSplitterWindow(parent, -1, wxPoint(0,0), parent->GetClientSize(), wxSP_3DBORDER | wxNO_3D)
  827. {
  828.     sequenceArea = new SequenceViewerWidget_SequenceArea(this);
  829.     titleArea = new SequenceViewerWidget_TitleArea(this);
  830.     sequenceArea->SetTitleArea(titleArea);
  831.     titleArea->SetSequenceArea(sequenceArea);
  832.     SplitVertically(titleArea, sequenceArea);
  833. }
  834. SequenceViewerWidget::~SequenceViewerWidget(void)
  835. {
  836. }
  837. void SequenceViewerWidget::OnDoubleClickSash(int x, int y)
  838. {
  839.     Unsplit(titleArea);
  840. }
  841. void SequenceViewerWidget::TitleAreaOn(void)
  842. {
  843.     if (!IsSplit()) {
  844.         titleArea->Show(true);
  845.         SplitVertically(titleArea, sequenceArea, titleArea->GetMaxTitleWidth() + 10);
  846.     }
  847. }
  848. void SequenceViewerWidget::TitleAreaOff(void)
  849. {
  850.     if (IsSplit())
  851.         Unsplit(titleArea);
  852. }
  853. void SequenceViewerWidget::TitleAreaToggle(void)
  854. {
  855.     if (IsSplit())
  856.         Unsplit(titleArea);
  857.     else {
  858.         titleArea->Show(true);
  859.         SplitVertically(titleArea, sequenceArea, titleArea->GetMaxTitleWidth() + 10);
  860.     }
  861. }
  862. bool SequenceViewerWidget::AttachAlignment(ViewableAlignment *newAlignment, int initX, int initY)
  863. {
  864.     // do titles first, since on Mac sequence area update causes title redraw
  865.     titleArea->ShowTitles(newAlignment);
  866.     sequenceArea->AttachAlignment(newAlignment, initX, initY);
  867.     SetSashPosition(titleArea->GetMaxTitleWidth() + 10, true);
  868. return true;
  869. }
  870. void SequenceViewerWidget::SetMouseMode(eMouseMode mode)
  871. {
  872.     sequenceArea->SetMouseMode(mode);
  873. }
  874. SequenceViewerWidget::eMouseMode SequenceViewerWidget::GetMouseMode(void) const
  875. {
  876.     return sequenceArea->GetMouseMode();
  877. }
  878. void SequenceViewerWidget::SetBackgroundColor(const wxColor& backgroundColor)
  879. {
  880.     sequenceArea->SetBackgroundColor(backgroundColor);
  881.     titleArea->SetBackgroundColor(backgroundColor);
  882. }
  883. void SequenceViewerWidget::SetCharacterFont(wxFont *font)
  884. {
  885.     wxFont *newFont = new wxFont(font->GetPointSize(), font->GetFamily(),
  886.         wxNORMAL, wxNORMAL, false, font->GetFaceName(), font->GetDefaultEncoding());
  887.     sequenceArea->SetCharacterFont(newFont);
  888.     newFont = new wxFont(font->GetPointSize(), font->GetFamily(),
  889.         wxITALIC, wxNORMAL, false, font->GetFaceName(), font->GetDefaultEncoding());
  890.     titleArea->SetCharacterFont(newFont, sequenceArea->GetCellHeight());
  891.     delete font;
  892.     // toggle title area twice to reset the sash to the right width - crude but effective
  893.     TitleAreaToggle();
  894.     TitleAreaToggle();
  895.     Refresh(true);
  896. }
  897. void SequenceViewerWidget::SetRubberbandColor(const wxColor& rubberbandColor)
  898. {
  899.     sequenceArea->SetRubberbandColor(rubberbandColor);
  900. }
  901. void SequenceViewerWidget::ScrollTo(int column, int row)
  902. {
  903.     sequenceArea->Scroll(column, row);
  904. }
  905. void SequenceViewerWidget::GetScroll(int *vsX, int *vsY) const
  906. {
  907.     sequenceArea->GetViewStart(vsX, vsY);
  908. }
  909. void SequenceViewerWidget::MakeCharacterVisible(int column, int row) const
  910. {
  911.     int vsX, vsY, nCells;
  912.     sequenceArea->GetViewStart(&vsX, &vsY);
  913.     // scroll horizontally if necessary
  914.     if (column >= 0) {
  915.         nCells = sequenceArea->GetClientSize().GetWidth() / sequenceArea->cellWidth;
  916.         if (column < vsX || column >= vsX + nCells) {
  917.             vsX = column - nCells / 2;
  918.             if (vsX < 0) vsX = 0;
  919.         }
  920.     }
  921.     // scroll vertically if necessary
  922.     if (row >= 0) {
  923.         nCells = sequenceArea->GetClientSize().GetHeight() / sequenceArea->cellHeight;
  924.         if (row < vsY || row >= vsY + nCells) {
  925.             vsY = row - nCells / 2;
  926.             if (vsY < 0) vsY = 0;
  927.         }
  928.     }
  929.     sequenceArea->Scroll(vsX, vsY);
  930. }
  931. void SequenceViewerWidget::Refresh(bool eraseBackground, const wxRect *rect)
  932. {
  933.     sequenceArea->Refresh(eraseBackground, rect);
  934.     titleArea->Refresh(eraseBackground, rect);
  935. }
  936. /*
  937. * ---------------------------------------------------------------------------
  938. * $Log: sequence_viewer_widget.cpp,v $
  939. * Revision 1000.2  2004/06/01 18:29:15  gouriano
  940. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.42
  941. *
  942. * Revision 1.42  2004/05/22 15:45:53  thiessen
  943. * support mouse wheel; update status bar on scroll
  944. *
  945. * Revision 1.41  2004/05/21 21:41:39  gorelenk
  946. * Added PCH ncbi_pch.hpp
  947. *
  948. * Revision 1.40  2004/03/15 18:32:03  thiessen
  949. * prefer prefix vs. postfix ++/-- operators
  950. *
  951. * Revision 1.39  2004/02/19 17:05:10  thiessen
  952. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  953. *
  954. * Revision 1.38  2003/02/03 19:20:06  thiessen
  955. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  956. *
  957. * Revision 1.37  2003/01/22 14:47:30  thiessen
  958. * cache PSSM in BlockMultipleAlignment
  959. *
  960. * Revision 1.36  2002/10/07 13:29:32  thiessen
  961. * add double-click -> show row to taxonomy tree
  962. *
  963. * Revision 1.35  2002/08/15 22:13:16  thiessen
  964. * update for wx2.3.2+ only; add structure pick dialog; fix MultitextDialog bug
  965. *
  966. * Revision 1.34  2002/04/27 16:32:14  thiessen
  967. * fix small leaks/bugs found by BoundsChecker
  968. *
  969. * Revision 1.33  2002/04/26 13:46:38  thiessen
  970. * comment out all blast/pssm methods
  971. *
  972. * Revision 1.32  2002/02/22 14:24:01  thiessen
  973. * sort sequences in reject dialog ; general identifier comparison
  974. *
  975. * Revision 1.31  2002/02/21 12:26:30  thiessen
  976. * fix row delete bug ; remember threader options
  977. *
  978. * Revision 1.30  2002/02/05 18:53:25  thiessen
  979. * scroll to residue in sequence windows when selected in structure window
  980. *
  981. * Revision 1.29  2001/11/01 19:01:45  thiessen
  982. * use meta key instead of ctrl on Mac
  983. *
  984. * Revision 1.28  2001/09/26 15:27:54  thiessen
  985. * tweak sequence viewer widget for wx2.3.2, tweak cdd annotation
  986. *
  987. * Revision 1.27  2001/08/14 17:18:22  thiessen
  988. * add user font selection, store in registry
  989. *
  990. * Revision 1.26  2001/07/19 19:14:38  thiessen
  991. * working CDD alignment annotator ; misc tweaks
  992. *
  993. * Revision 1.25  2001/06/07 19:05:38  thiessen
  994. * functional (although incomplete) render settings panel ; highlight title - not sequence - upon mouse click
  995. *
  996. * Revision 1.24  2001/05/31 18:47:09  thiessen
  997. * add preliminary style dialog; remove LIST_TYPE; add thread single and delete all; misc tweaks
  998. *
  999. * Revision 1.23  2001/05/31 14:32:33  thiessen
  1000. * tweak font handling
  1001. *
  1002. * Revision 1.22  2001/05/22 19:09:31  thiessen
  1003. * many minor fixes to compile/run on Solaris/GTK
  1004. *
  1005. * Revision 1.21  2001/05/03 14:39:14  thiessen
  1006. * put ViewableAlignment in its own (non-wx) header
  1007. *
  1008. * Revision 1.20  2001/05/02 16:35:15  thiessen
  1009. * launch entrez web page on sequence identifier
  1010. *
  1011. * Revision 1.19  2001/04/18 15:46:53  thiessen
  1012. * show description, length, and PDB numbering in status line
  1013. *
  1014. * Revision 1.18  2001/04/04 00:27:15  thiessen
  1015. * major update - add merging, threader GUI controls
  1016. *
  1017. * Revision 1.17  2000/12/21 23:42:16  thiessen
  1018. * load structures from cdd's
  1019. *
  1020. * Revision 1.16  2000/11/02 16:56:02  thiessen
  1021. * working editor undo; dynamic slave transforms
  1022. *
  1023. * Revision 1.15  2000/10/16 20:03:07  thiessen
  1024. * working block creation
  1025. *
  1026. * Revision 1.14  2000/10/12 16:22:45  thiessen
  1027. * working block split
  1028. *
  1029. * Revision 1.13  2000/10/05 18:34:43  thiessen
  1030. * first working editing operation
  1031. *
  1032. * Revision 1.12  2000/10/04 17:41:31  thiessen
  1033. * change highlight color (cell background) handling
  1034. *
  1035. * Revision 1.11  2000/10/03 18:59:23  thiessen
  1036. * added row/column selection
  1037. *
  1038. * Revision 1.10  2000/10/02 23:25:23  thiessen
  1039. * working sequence identifier window in sequence viewer
  1040. *
  1041. * Revision 1.9  2000/09/20 22:22:28  thiessen
  1042. * working conservation coloring; split and center unaligned justification
  1043. *
  1044. * Revision 1.8  2000/09/14 14:55:35  thiessen
  1045. * add row reordering; misc fixes
  1046. *
  1047. * Revision 1.7  2000/09/12 01:47:39  thiessen
  1048. * fix minor but obscure bug
  1049. *
  1050. * Revision 1.6  2000/09/11 22:57:33  thiessen
  1051. * working highlighting
  1052. *
  1053. * Revision 1.5  2000/09/11 01:46:16  thiessen
  1054. * working messenger for sequence<->structure window communication
  1055. *
  1056. * Revision 1.4  2000/09/09 14:35:15  thiessen
  1057. * fix wxWin problem with large alignments
  1058. *
  1059. * Revision 1.3  2000/09/07 21:41:40  thiessen
  1060. * fix return type of min_max
  1061. *
  1062. * Revision 1.2  2000/09/07 17:37:35  thiessen
  1063. * minor fixes
  1064. *
  1065. * Revision 1.1  2000/09/03 18:46:49  thiessen
  1066. * working generalized sequence viewer
  1067. *
  1068. * Revision 1.2  2000/08/30 23:46:28  thiessen
  1069. * working alignment display
  1070. *
  1071. * Revision 1.1  2000/08/30 19:48:42  thiessen
  1072. * working sequence window
  1073. *
  1074. */