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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: cn3d_glcanvas.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:28:15  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: cn3d_glcanvas.cpp,v 1000.2 2004/06/01 18:28: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. *      OpenGL canvas object
  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 <memory>
  47. #include <wx/fontutil.h>
  48. #include <wx/image.h>
  49. #include "cn3d_glcanvas.hpp"
  50. #include "opengl_renderer.hpp"
  51. #include "cn3d_tools.hpp"
  52. #include "structure_set.hpp"
  53. USING_NCBI_SCOPE;
  54. USING_SCOPE(objects);
  55. BEGIN_SCOPE(Cn3D)
  56. BEGIN_EVENT_TABLE(Cn3DGLCanvas, wxGLCanvas)
  57.     EVT_SIZE                (Cn3DGLCanvas::OnSize)
  58.     EVT_PAINT               (Cn3DGLCanvas::OnPaint)
  59.     EVT_MOUSE_EVENTS        (Cn3DGLCanvas::OnMouseEvent)
  60.     EVT_ERASE_BACKGROUND    (Cn3DGLCanvas::OnEraseBackground)
  61. END_EVENT_TABLE()
  62. Cn3DGLCanvas::Cn3DGLCanvas(wxWindow *parent, int *attribList) :
  63.     wxGLCanvas(parent, -1, wxPoint(0, 0), wxDefaultSize, wxSUNKEN_BORDER, "Cn3DGLCanvas", attribList),
  64.     structureSet(NULL), suspended(false)
  65. {
  66.     renderer = new OpenGLRenderer(this);
  67. }
  68. Cn3DGLCanvas::~Cn3DGLCanvas(void)
  69. {
  70.     if (structureSet) delete structureSet;
  71.     delete renderer;
  72. }
  73. void Cn3DGLCanvas::SuspendRendering(bool suspend)
  74. {
  75.     suspended = suspend;
  76.     if (!suspend) {
  77.         wxSizeEvent resize(GetSize());
  78.         OnSize(resize);
  79.     }
  80. }
  81. void Cn3DGLCanvas::SetGLFontFromRegistry(double fontScale)
  82. {
  83.     // get font info from registry, and create wxFont
  84.     string nativeFont;
  85.     if (!RegistryGetString(REG_OPENGL_FONT_SECTION, REG_FONT_NATIVE_FONT_INFO, &nativeFont))
  86.     {
  87.         ERRORMSG("Cn3DGLCanvas::SetGLFontFromRegistry() - error getting font info from registry");
  88.         return;
  89.     }
  90.     // create new font - assignment uses object reference to copy
  91.     wxNativeFontInfo fontInfo;
  92.     if (!fontInfo.FromString(nativeFont.c_str())) {
  93.         ERRORMSG("Cn3DGLCanvas::SetGLFontFromRegistry() - can't set wxNativeFontInfo fron native font string");
  94.         return;
  95.     }
  96. #if wxCHECK_VERSION(2,3,4)
  97.     if (fontScale != 1.0 && fontScale > 0.0)
  98.         fontInfo.SetPointSize(fontScale * fontInfo.GetPointSize());
  99. #endif
  100.     auto_ptr<wxFont> newFont(wxFont::New(fontInfo));
  101.     if (!newFont.get() || !newFont->Ok()) {
  102.         ERRORMSG("Cn3DGLCanvas::SetGLFontFromRegistry() - can't get wxFont from wxNativeFontInfo");
  103.         return;
  104.     }
  105.     font = *newFont;    // copy font
  106.     // set up font display lists in dc and renderer
  107.     if (!memoryDC.Ok()) {
  108.         wxBitmap tinyBitmap(1, 1, -1);
  109.         memoryBitmap = tinyBitmap; // copies by reference
  110.         memoryDC.SelectObject(memoryBitmap);
  111.     }
  112.     memoryDC.SetFont(font);
  113.     renderer->SetGLFont(0, 256, renderer->FONT_BASE);
  114. }
  115. #define MYMAX(a, b) (((a) >= (b)) ? (a) : (b))
  116. bool Cn3DGLCanvas::MeasureText(const string& text, int *width, int *height, int *centerX, int *centerY)
  117. {
  118.     wxCoord w, h;
  119.     memoryDC.GetTextExtent(text.c_str(), &w, &h);
  120.     *width = (int) w;
  121.     *height = (int) h;
  122.     // GetTextExtent measures text+background when a character is drawn, but for OpenGL, we need
  123.     // to measure actual character pixels more precisely: render characters into memory bitmap,
  124.     // then find the minimal rect that contains actual character pixels, not text background
  125.     if (memoryBitmap.GetWidth() < w || memoryBitmap.GetHeight() < h) {
  126.         wxBitmap biggerBitmap(MYMAX(memoryBitmap.GetWidth(), w), MYMAX(memoryBitmap.GetHeight(), h), -1);
  127.         memoryBitmap = biggerBitmap; // copies by reference
  128.         memoryDC.SelectObject(memoryBitmap);
  129.     }
  130.     memoryDC.SetBackground(*wxBLUE_BRUSH);
  131.     memoryDC.SetBackgroundMode(wxSOLID);
  132.     memoryDC.SetTextBackground(*wxGREEN);
  133.     memoryDC.SetTextForeground(*wxRED);
  134.     memoryDC.BeginDrawing();
  135.     memoryDC.Clear();
  136.     memoryDC.DrawText(text.c_str(), 0, 0);
  137.     memoryDC.EndDrawing();
  138.     // then convert bitmap to image so that we can read individual pixels (ugh...)
  139.     wxImage image(memoryBitmap.ConvertToImage());
  140. //    wxInitAllImageHandlers();
  141. //    image.SaveFile("text.png", wxBITMAP_TYPE_PNG); // for testing
  142.     // now find extent of actual (red) text pixels; wx coords put (0,0) at upper left
  143.     int x, y, top = image.GetHeight(), left = image.GetWidth(), bottom = -1, right = -1;
  144.     for (x=0; x<image.GetWidth(); ++x) {
  145.         for (y=0; y<image.GetHeight(); ++y) {
  146.             if (image.GetRed(x, y) >= 128) { // character pixel here
  147.                 if (y < top) top = y;
  148.                 if (x < left) left = x;
  149.                 if (y > bottom) bottom = y;
  150.                 if (x > right) right = x;
  151.             }
  152.         }
  153.     }
  154.     if (bottom < 0 || right < 0) {
  155.         WARNINGMSG("Cn3DGLCanvas::MeasureText() - no character pixels found!");
  156.         *centerX = *centerY = 0;
  157.         return false;
  158.     }
  159. //    TESTMSG("top: " << top << ", left: " << left << ", bottom: " << bottom << ", right: " << right);
  160.     // set center{X,Y} to center of drawn glyph relative to bottom left
  161.     *centerX = (int) (((double) (right - left)) / 2 + 0.5);
  162.     *centerY = (int) (((double) (bottom - top)) / 2 + 0.5);
  163.     return true;
  164. }
  165. void Cn3DGLCanvas::OnPaint(wxPaintEvent& event)
  166. {
  167.     // This is a dummy, to avoid an endless succession of paint messages.
  168.     // OnPaint handlers must always create a wxPaintDC.
  169.     wxPaintDC dc(this);
  170.     if (!GetContext() || !renderer || suspended) return;
  171.     SetCurrent();
  172.     renderer->Display();
  173.     SwapBuffers();
  174. }
  175. void Cn3DGLCanvas::OnSize(wxSizeEvent& event)
  176. {
  177.     if (suspended || !GetContext()) return;
  178.     SetCurrent();
  179.     // this is necessary to update the context on some platforms
  180.     wxGLCanvas::OnSize(event);
  181.     // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
  182.     int w, h;
  183.     GetClientSize(&w, &h);
  184.     glViewport(0, 0, (GLint) w, (GLint) h);
  185.     renderer->NewView();
  186. }
  187. void Cn3DGLCanvas::OnMouseEvent(wxMouseEvent& event)
  188. {
  189.     static bool dragging = false;
  190.     static long last_x, last_y;
  191.     if (!GetContext() || !renderer || suspended) return;
  192.     SetCurrent();
  193. // in wxGTK >= 2.3.2, this causes a system crash on some Solaris machines...
  194. #if !defined(__WXGTK__)
  195.     // keep mouse focus while holding down button
  196.     if (event.LeftDown()) CaptureMouse();
  197.     if (event.LeftUp()) ReleaseMouse();
  198. #endif
  199.     if (event.LeftIsDown()) {
  200.         if (!dragging) {
  201.             dragging = true;
  202.         } else {
  203.             OpenGLRenderer::eViewAdjust action;
  204.             if (event.ShiftDown())
  205.                 action = OpenGLRenderer::eXYTranslateHV;    // shift-drag = translate
  206. #ifdef __WXMAC__
  207.             else if (event.MetaDown())      // control key + mouse doesn't work on Mac?
  208. #else
  209.             else if (event.ControlDown())
  210. #endif
  211.                 action = OpenGLRenderer::eZoomH;            // ctrl-drag = zoom
  212.             else
  213.                 action = OpenGLRenderer::eXYRotateHV;       // normal rotate
  214.             renderer->ChangeView(action, event.GetX() - last_x, event.GetY() - last_y);
  215.             Refresh(false);
  216.         }
  217.         last_x = event.GetX();
  218.         last_y = event.GetY();
  219.     } else {
  220.         dragging = false;
  221.     }
  222.     if (event.LeftDClick()) {   // double-click = select, +ctrl = set center
  223.         unsigned int name;
  224.         if (structureSet && renderer->GetSelected(event.GetX(), event.GetY(), &name))
  225.             structureSet->SelectedAtom(name,
  226. #ifdef __WXMAC__
  227.                 event.MetaDown()      // control key + mouse doesn't work on Mac?
  228. #else
  229.                 event.ControlDown()
  230. #endif
  231.             );
  232.     }
  233. }
  234. void Cn3DGLCanvas::OnEraseBackground(wxEraseEvent& event)
  235. {
  236.     // Do nothing, to avoid flashing.
  237. }
  238. END_SCOPE(Cn3D)
  239. /*
  240. * ---------------------------------------------------------------------------
  241. * $Log: cn3d_glcanvas.cpp,v $
  242. * Revision 1000.2  2004/06/01 18:28:15  gouriano
  243. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  244. *
  245. * Revision 1.5  2004/05/21 21:41:39  gorelenk
  246. * Added PCH ncbi_pch.hpp
  247. *
  248. * Revision 1.4  2004/03/15 18:23:01  thiessen
  249. * prefer prefix vs. postfix ++/-- operators
  250. *
  251. * Revision 1.3  2004/02/19 17:04:50  thiessen
  252. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  253. *
  254. * Revision 1.2  2003/03/14 19:22:59  thiessen
  255. * add CommandProcessor to handle file-message commands; fixes for GCC 2.9
  256. *
  257. * Revision 1.1  2003/03/13 14:26:18  thiessen
  258. * add file_messaging module; split cn3d_main_wxwin into cn3d_app, cn3d_glcanvas, structure_window, cn3d_tools
  259. *
  260. */