home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / samples / dragimag / dragimag.cpp < prev    next >
C/C++ Source or Header  |  2002-12-16  |  14KB  |  499 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        dragimag.cpp
  3. // Purpose:     wxDragImage sample
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     28/2/2000
  7. // RCS-ID:      $Id: dragimag.cpp,v 1.13.2.1 2002/12/14 18:19:40 MBN Exp $
  8. // Copyright:   (c) Julian Smart
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx/wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #ifdef __BORLANDC__
  16. #pragma hdrstop
  17. #endif
  18.  
  19. #ifndef WX_PRECOMP
  20. #include "wx/wx.h"
  21. #endif
  22.  
  23. #include "wx/image.h"
  24.  
  25. // Under Windows, change this to 1
  26. // to use wxGenericDragImage
  27.  
  28. #define wxUSE_GENERIC_DRAGIMAGE 1
  29.  
  30. #if wxUSE_GENERIC_DRAGIMAGE
  31. #include "wx/generic/dragimgg.h"
  32. #define wxDragImage wxGenericDragImage
  33. #else
  34. #include "wx/dragimag.h"
  35. #endif
  36.  
  37. #include "dragimag.h"
  38.  
  39. #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
  40. #include "mondrian.xpm"
  41. #include "dragicon.xpm"
  42. #endif
  43.  
  44. // main program
  45.  
  46. IMPLEMENT_APP(MyApp)
  47.  
  48. // MyCanvas
  49.  
  50. IMPLEMENT_CLASS(MyCanvas, wxScrolledWindow)
  51.  
  52. BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  53.   EVT_PAINT(MyCanvas::OnPaint)
  54.   EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackground)
  55.   EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
  56. END_EVENT_TABLE()
  57.  
  58. MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id,
  59.                     const wxPoint &pos, const wxSize &size )
  60.         : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER )
  61. {
  62.     SetBackgroundColour(* wxWHITE);
  63.  
  64.     SetCursor(wxCursor(wxCURSOR_ARROW));
  65.  
  66.     m_dragMode = TEST_DRAG_NONE;
  67.     m_draggedShape = (DragShape*) NULL;
  68.     m_dragImage = (wxDragImage*) NULL;
  69.     m_currentlyHighlighted = (DragShape*) NULL;
  70. }
  71.  
  72. MyCanvas::~MyCanvas()
  73. {
  74.     ClearShapes();
  75.  
  76.     if (m_dragImage)
  77.         delete m_dragImage;
  78. }
  79.  
  80. void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
  81. {
  82.     wxPaintDC dc( this );
  83.     PrepareDC( dc );
  84.  
  85.     DrawShapes(dc);
  86. }
  87.  
  88. void MyCanvas::OnEraseBackground(wxEraseEvent& event)
  89. {
  90.     if (wxGetApp().GetBackgroundBitmap().Ok())
  91.     {
  92.         wxSize sz = GetClientSize();
  93.         wxRect rect(0, 0, sz.x, sz.y);
  94.         
  95.         if (event.GetDC())
  96.         {
  97.             wxGetApp().TileBitmap(rect, *(event.GetDC()), wxGetApp().GetBackgroundBitmap());
  98.         }
  99.         else
  100.         {
  101.             wxClientDC dc(this);
  102.             wxGetApp().TileBitmap(rect, dc, wxGetApp().GetBackgroundBitmap());
  103.         }
  104.     }
  105.     else
  106.         event.Skip(); // The official way of doing it
  107. }
  108.  
  109. void MyCanvas::OnMouseEvent(wxMouseEvent& event)
  110. {
  111.     if (event.LeftDown())
  112.     {
  113.         DragShape* shape = FindShape(event.GetPosition());
  114.         if (shape)
  115.         {
  116.             // We tentatively start dragging, but wait for
  117.             // mouse movement before dragging properly.
  118.  
  119.             m_dragMode = TEST_DRAG_START;
  120.             m_dragStartPos = event.GetPosition();
  121.             m_draggedShape = shape;
  122.         }
  123.     }
  124.     else if (event.LeftUp() && m_dragMode != TEST_DRAG_NONE)
  125.     {
  126.         // Finish dragging
  127.  
  128.         m_dragMode = TEST_DRAG_NONE;
  129.  
  130.         if (!m_draggedShape || !m_dragImage)
  131.             return;
  132.  
  133.         m_draggedShape->SetPosition(m_draggedShape->GetPosition()
  134.                                     + event.GetPosition() - m_dragStartPos);
  135.  
  136.         m_dragImage->Hide();
  137.         m_dragImage->EndDrag();
  138.         delete m_dragImage;
  139.         m_dragImage = NULL;
  140.  
  141.         wxClientDC dc(this);
  142.         if (m_currentlyHighlighted)
  143.         {
  144.             m_currentlyHighlighted->Draw(dc);
  145.         }
  146.         m_draggedShape->SetShow(TRUE);
  147.         m_draggedShape->Draw(dc);
  148.  
  149.         m_currentlyHighlighted = (DragShape*) NULL;
  150.  
  151.         m_draggedShape = (DragShape*) NULL;
  152.     }
  153.     else if (event.Dragging() && m_dragMode != TEST_DRAG_NONE)
  154.     {
  155.         if (m_dragMode == TEST_DRAG_START)
  156.         {
  157.             // We will start dragging if we've moved beyond a couple of pixels
  158.  
  159.             int tolerance = 2;
  160.             int dx = abs(event.GetPosition().x - m_dragStartPos.x);
  161.             int dy = abs(event.GetPosition().y - m_dragStartPos.y);
  162.             if (dx <= tolerance && dy <= tolerance)
  163.                 return;
  164.  
  165.             // Start the drag.
  166.             m_dragMode = TEST_DRAG_DRAGGING;
  167.  
  168.             if (m_dragImage)
  169.                 delete m_dragImage;
  170.  
  171.             // Erase the dragged shape from the canvas
  172.             m_draggedShape->SetShow(FALSE);
  173.             wxClientDC dc(this);
  174.             EraseShape(m_draggedShape, dc);
  175.             DrawShapes(dc);
  176.  
  177.             switch (m_draggedShape->GetDragMethod())
  178.             {
  179.                 case SHAPE_DRAG_BITMAP:
  180.                 {
  181.                     m_dragImage = new wxDragImage(m_draggedShape->GetBitmap(), wxCursor(wxCURSOR_HAND));
  182.                     break;
  183.                 }
  184.                 case SHAPE_DRAG_TEXT:
  185.                 {
  186.                     m_dragImage = new wxDragImage(wxString(_T("Dragging some test text")), wxCursor(wxCURSOR_HAND));
  187.                     break;
  188.                 }
  189.                 case SHAPE_DRAG_ICON:
  190.                 {
  191.                     // Can anyone explain why this test is necessary,
  192.                     // to prevent a gcc error?
  193. #if defined(__WXMOTIF__) || defined(__WXX11__)
  194.                     wxIcon icon(dragicon_xpm);
  195. #else
  196.                     wxIcon icon(wxICON(dragicon));
  197. #endif
  198.                     
  199.                     m_dragImage = new wxDragImage(icon, wxCursor(wxCURSOR_HAND));
  200.                     break;
  201.                 }
  202.             }
  203.  
  204.             bool fullScreen = wxGetApp().GetUseScreen();
  205.  
  206.             // The offset between the top-left of the shape image and the current shape position
  207.             wxPoint beginDragHotSpot = m_dragStartPos - m_draggedShape->GetPosition();
  208.             
  209.             // Now we do this inside the implementation: always assume
  210.             // coordinates relative to the capture window (client coordinates)
  211.  
  212.             //if (fullScreen)
  213.             //    beginDragHotSpot -= ClientToScreen(wxPoint(0, 0));
  214.             
  215.             if (!m_dragImage->BeginDrag(beginDragHotSpot, this, fullScreen))
  216.             {
  217.                 delete m_dragImage;
  218.                 m_dragImage = (wxDragImage*) NULL;
  219.                 m_dragMode = TEST_DRAG_NONE;
  220.                 
  221.             } else
  222.             {
  223.                 m_dragImage->Move(event.GetPosition());
  224.                 m_dragImage->Show();
  225.             }
  226.         }
  227.         else if (m_dragMode == TEST_DRAG_DRAGGING)
  228.         {
  229.             // We're currently dragging. See if we're over another shape.
  230.             DragShape* onShape = FindShape(event.GetPosition());
  231.  
  232.             bool mustUnhighlightOld = FALSE;
  233.             bool mustHighlightNew = FALSE;
  234.  
  235.             if (m_currentlyHighlighted)
  236.             {
  237.                 if ((onShape == (DragShape*) NULL) || (m_currentlyHighlighted != onShape))
  238.                     mustUnhighlightOld = TRUE;
  239.             }
  240.  
  241.             if (onShape && (onShape != m_currentlyHighlighted) && onShape->IsShown())
  242.                 mustHighlightNew = TRUE;
  243.  
  244.             if (mustUnhighlightOld || mustHighlightNew)
  245.                 m_dragImage->Hide();
  246.  
  247.             // Now with the drag image switched off, we can change the window contents.
  248.  
  249.             if (mustUnhighlightOld)
  250.             {
  251.                 wxClientDC clientDC(this);
  252.                 m_currentlyHighlighted->Draw(clientDC);
  253.                 m_currentlyHighlighted = (DragShape*) NULL;
  254.             }
  255.             if (mustHighlightNew)
  256.             {
  257.                 wxClientDC clientDC(this);
  258.                 m_currentlyHighlighted = onShape;
  259.                 m_currentlyHighlighted->Draw(clientDC, wxINVERT);
  260.             }
  261.  
  262.             // Move and show the image again
  263.             m_dragImage->Move(event.GetPosition());
  264.  
  265.             if (mustUnhighlightOld || mustHighlightNew)
  266.                  m_dragImage->Show();
  267.         }
  268.     }
  269. }
  270.  
  271. void MyCanvas::DrawShapes(wxDC& dc)
  272. {
  273.     wxNode* node = m_displayList.First();
  274.     while (node)
  275.     {
  276.         DragShape* shape = (DragShape*) node->Data();
  277.         if (shape->IsShown())
  278.           shape->Draw(dc);
  279.         node = node->Next();
  280.     }
  281. }
  282.  
  283. void MyCanvas::EraseShape(DragShape* shape, wxDC& dc)
  284. {
  285.     wxSize sz = GetClientSize();
  286.     wxRect rect(0, 0, sz.x, sz.y);
  287.  
  288.     wxRect rect2(shape->GetRect());
  289.     dc.SetClippingRegion(rect2.x, rect2.y, rect2.width, rect2.height);
  290.         
  291.     wxGetApp().TileBitmap(rect, dc, wxGetApp().GetBackgroundBitmap());
  292.  
  293.     dc.DestroyClippingRegion();
  294. }
  295.  
  296. void MyCanvas::ClearShapes()
  297. {
  298.     wxNode* node = m_displayList.First();
  299.     while (node)
  300.     {
  301.         DragShape* shape = (DragShape*) node->Data();
  302.         delete shape;
  303.         node = node->Next();
  304.     }
  305.     m_displayList.Clear();
  306. }
  307.  
  308. DragShape* MyCanvas::FindShape(const wxPoint& pt) const
  309. {
  310.     wxNode* node = m_displayList.First();
  311.     while (node)
  312.     {
  313.         DragShape* shape = (DragShape*) node->Data();
  314.         if (shape->HitTest(pt))
  315.             return shape;
  316.         node = node->Next();
  317.     }
  318.     return (DragShape*) NULL;
  319. }
  320.  
  321. // MyFrame
  322. IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
  323.  
  324. BEGIN_EVENT_TABLE(MyFrame,wxFrame)
  325.   EVT_MENU    (wxID_ABOUT, MyFrame::OnAbout)
  326.   EVT_MENU    (wxID_EXIT,  MyFrame::OnQuit)
  327. END_EVENT_TABLE()
  328.  
  329. MyFrame::MyFrame()
  330.        : wxFrame( (wxFrame *)NULL, -1, _T("wxDragImage sample"),
  331.                   wxPoint(20,20), wxSize(470,360) )
  332. {
  333.   wxMenu *file_menu = new wxMenu();
  334.   file_menu->Append( wxID_ABOUT, _T("&About..."));
  335.   file_menu->Append( TEST_USE_SCREEN, _T("&Use whole screen for dragging"), _T("Use whole screen"), TRUE);
  336.   file_menu->Append( wxID_EXIT, _T("E&xit"));
  337.  
  338.   wxMenuBar *menu_bar = new wxMenuBar();
  339.   menu_bar->Append(file_menu, _T("&File"));
  340.  
  341.   SetMenuBar( menu_bar );
  342.  
  343.   CreateStatusBar(2);
  344.   int widths[] = { -1, 100 };
  345.   SetStatusWidths( 2, widths );
  346.  
  347.   m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(10,10) );
  348. }
  349.  
  350. void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
  351. {
  352.   Close( TRUE );
  353. }
  354.  
  355. void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
  356. {
  357.     (void)wxMessageBox( _T("wxDragImage demo\n")
  358.                         _T("Julian Smart (c) 2000"),
  359.                         _T("About wxDragImage Demo"), 
  360.                         wxICON_INFORMATION | wxOK );
  361. }
  362.  
  363. //-----------------------------------------------------------------------------
  364. // MyApp
  365. //-----------------------------------------------------------------------------
  366.  
  367. BEGIN_EVENT_TABLE(MyApp, wxApp)
  368.     EVT_MENU(TEST_USE_SCREEN, MyApp::OnUseScreen)
  369. END_EVENT_TABLE()
  370.  
  371. MyApp::MyApp()
  372. {
  373.     // Drag across whole screen
  374.     m_useScreen = FALSE;
  375. }
  376.  
  377. bool MyApp::OnInit()
  378. {
  379. #if wxUSE_LIBPNG
  380.     wxImage::AddHandler( new wxPNGHandler );
  381. #endif
  382.  
  383.     wxImage image;
  384.     if (image.LoadFile(_T("backgrnd.png"), wxBITMAP_TYPE_PNG))
  385.     {
  386.         m_background = wxBitmap(image);
  387.     }
  388.  
  389.     MyFrame *frame = new MyFrame();
  390.  
  391.     wxString rootName(_T("shape0"));
  392.  
  393.     int i;
  394.     for (i = 1; i < 4; i++)
  395.     {
  396.         wxString filename;
  397.         filename.Printf(wxT("%s%d.png"), (const wxChar*)rootName, i);
  398.     /* For some reason under wxX11, the 2nd LoadFile in this loop fails, with
  399.        a BadMatch inside CreateFromImage (inside ConvertToBitmap). This happens even if you copy
  400.        the first file over the second file. */
  401.         if (image.LoadFile(filename, wxBITMAP_TYPE_PNG))
  402.         {
  403.             DragShape* newShape = new DragShape(wxBitmap(image));
  404.             newShape->SetPosition(wxPoint(i*50, i*50));
  405.  
  406.             if (i == 2)
  407.                 newShape->SetDragMethod(SHAPE_DRAG_TEXT);
  408.             else if (i == 3)
  409.                 newShape->SetDragMethod(SHAPE_DRAG_ICON);
  410.             else
  411.                 newShape->SetDragMethod(SHAPE_DRAG_BITMAP);
  412.             frame->GetCanvas()->GetDisplayList().Append(newShape);
  413.         }
  414.     }
  415.  
  416. #if 0
  417.     // Under Motif or GTK, this demonstrates that
  418.     // wxScreenDC only gets the root window content.
  419.     // We need to be able to copy the overall content
  420.     // for full-screen dragging to work.
  421.     int w, h;
  422.     wxDisplaySize(& w, & h);
  423.     wxBitmap bitmap(w, h);
  424.  
  425.     wxScreenDC dc;
  426.     wxMemoryDC memDC;
  427.     memDC.SelectObject(bitmap);
  428.     memDC.Blit(0, 0, w, h, & dc, 0, 0);
  429.     memDC.SelectObject(wxNullBitmap);
  430.     m_background = bitmap;
  431. #endif
  432.  
  433.     frame->Show( TRUE );
  434.  
  435.     return TRUE;
  436. }
  437.  
  438. int MyApp::OnExit()
  439. {
  440.     return 0;
  441. }
  442.  
  443. bool MyApp::TileBitmap(const wxRect& rect, wxDC& dc, wxBitmap& bitmap)
  444. {
  445.     int w = bitmap.GetWidth();
  446.     int h = bitmap.GetHeight();
  447.     
  448.     int i, j;
  449.     for (i = rect.x; i < rect.x + rect.width; i += w)
  450.     {
  451.         for (j = rect.y; j < rect.y + rect.height; j+= h)
  452.             dc.DrawBitmap(bitmap, i, j);
  453.     }
  454.     return TRUE;
  455. }
  456.  
  457. void MyApp::OnUseScreen(wxCommandEvent& event)
  458. {
  459.     m_useScreen = !m_useScreen;
  460. }
  461.  
  462. // DragShape
  463.  
  464. DragShape::DragShape(const wxBitmap& bitmap)
  465. {
  466.     m_bitmap = bitmap;
  467.     m_pos.x = 0;
  468.     m_pos.y = 0;
  469.     m_dragMethod = SHAPE_DRAG_BITMAP;
  470.     m_show = TRUE;
  471. }
  472.  
  473. DragShape::~DragShape()
  474. {
  475. }
  476.  
  477. bool DragShape::HitTest(const wxPoint& pt) const
  478. {
  479.     wxRect rect(GetRect());
  480.     return rect.Inside(pt.x, pt.y);
  481. }
  482.  
  483. bool DragShape::Draw(wxDC& dc, int op)
  484. {
  485.     if (m_bitmap.Ok())
  486.     {
  487.         wxMemoryDC memDC;
  488.         memDC.SelectObject(m_bitmap);
  489.     
  490.         dc.Blit(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight(),
  491.             & memDC, 0, 0, op, TRUE);
  492.  
  493.         return TRUE;
  494.     }
  495.     else
  496.         return FALSE;
  497. }
  498.  
  499.