dnd.cpp 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: dnd.cpp
  3. // Purpose: Drag and drop sample
  4. // Author: Vadim Zeitlin
  5. // Modified by:
  6. // Created: 04/01/98
  7. // Copyright:
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include "wx/wxprec.h"
  11. #ifdef __BORLANDC__
  12. #pragma hdrstop
  13. #endif
  14. #ifndef WX_PRECOMP
  15. #include "wx/wx.h"
  16. #endif
  17. #include "wx/dnd.h"
  18. #include "wx/dataobj.h"
  19. #include "wx/image.h"
  20. #include "wx/clipbrd.h"
  21. #include "wx/colordlg.h"
  22. #include "wx/metafile.h"
  23. #include "wx/dirctrl.h"
  24. #ifndef wxHAS_IMAGES_IN_RESOURCES
  25. #include "../sample.xpm"
  26. #if wxUSE_DRAG_AND_DROP
  27. #include "dnd_copy.xpm"
  28. #include "dnd_move.xpm"
  29. #include "dnd_none.xpm"
  30. #endif
  31. #endif
  32. #if wxUSE_DRAG_AND_DROP
  33. // ----------------------------------------------------------------------------
  34. // Derive two simple classes which just put in the listbox the strings (text or
  35. // file names) we drop on them
  36. // ----------------------------------------------------------------------------
  37. class DnDText : public wxTextDropTarget
  38. {
  39. public:
  40. DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
  41. virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text);
  42. private:
  43. wxListBox *m_pOwner;
  44. };
  45. class DnDFile : public wxFileDropTarget
  46. {
  47. public:
  48. DnDFile(wxListBox *pOwner = NULL) { m_pOwner = pOwner; }
  49. virtual bool OnDropFiles(wxCoord x, wxCoord y,
  50. const wxArrayString& filenames);
  51. private:
  52. wxListBox *m_pOwner;
  53. };
  54. // ----------------------------------------------------------------------------
  55. // Define a custom dtop target accepting URLs
  56. // ----------------------------------------------------------------------------
  57. class URLDropTarget : public wxDropTarget
  58. {
  59. public:
  60. URLDropTarget() { SetDataObject(new wxURLDataObject); }
  61. void OnDropURL(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxString& text)
  62. {
  63. // of course, a real program would do something more useful here...
  64. wxMessageBox(text, wxT("wxDnD sample: got URL"),
  65. wxICON_INFORMATION | wxOK);
  66. }
  67. // URLs can't be moved, only copied
  68. virtual wxDragResult OnDragOver(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
  69. wxDragResult WXUNUSED(def))
  70. {
  71. return wxDragLink; // At least IE 5.x needs wxDragLink, the
  72. // other browsers on MSW seem okay with it too.
  73. }
  74. // translate this to calls to OnDropURL() just for convenience
  75. virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
  76. {
  77. if ( !GetData() )
  78. return wxDragNone;
  79. OnDropURL(x, y, ((wxURLDataObject *)m_dataObject)->GetURL());
  80. return def;
  81. }
  82. };
  83. #endif // wxUSE_DRAG_AND_DROP
  84. // ----------------------------------------------------------------------------
  85. // Define a new application type
  86. // ----------------------------------------------------------------------------
  87. class DnDApp : public wxApp
  88. {
  89. public:
  90. virtual bool OnInit();
  91. };
  92. IMPLEMENT_APP(DnDApp)
  93. #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
  94. // ----------------------------------------------------------------------------
  95. // Define canvas class to show a bitmap
  96. // ----------------------------------------------------------------------------
  97. class DnDCanvasBitmap : public wxScrolledWindow
  98. {
  99. public:
  100. DnDCanvasBitmap(wxWindow *parent) : wxScrolledWindow(parent) { }
  101. void SetBitmap(const wxBitmap& bitmap)
  102. {
  103. m_bitmap = bitmap;
  104. SetScrollbars(10, 10,
  105. m_bitmap.GetWidth() / 10, m_bitmap.GetHeight() / 10);
  106. Refresh();
  107. }
  108. void OnPaint(wxPaintEvent& WXUNUSED(event))
  109. {
  110. wxPaintDC dc(this);
  111. if ( m_bitmap.IsOk() )
  112. {
  113. PrepareDC(dc);
  114. dc.DrawBitmap(m_bitmap, 0, 0);
  115. }
  116. }
  117. private:
  118. wxBitmap m_bitmap;
  119. wxDECLARE_EVENT_TABLE();
  120. };
  121. #if wxUSE_METAFILE
  122. // and the same thing fo metafiles
  123. class DnDCanvasMetafile : public wxScrolledWindow
  124. {
  125. public:
  126. DnDCanvasMetafile(wxWindow *parent) : wxScrolledWindow(parent) { }
  127. void SetMetafile(const wxMetafile& metafile)
  128. {
  129. m_metafile = metafile;
  130. SetScrollbars(10, 10,
  131. m_metafile.GetWidth() / 10, m_metafile.GetHeight() / 10);
  132. Refresh();
  133. }
  134. void OnPaint(wxPaintEvent&)
  135. {
  136. wxPaintDC dc(this);
  137. if ( m_metafile.IsOk() )
  138. {
  139. PrepareDC(dc);
  140. m_metafile.Play(&dc);
  141. }
  142. }
  143. private:
  144. wxMetafile m_metafile;
  145. wxDECLARE_EVENT_TABLE();
  146. };
  147. #endif // wxUSE_METAFILE
  148. // ----------------------------------------------------------------------------
  149. // Define a new frame type for the main frame
  150. // ----------------------------------------------------------------------------
  151. class DnDFrame : public wxFrame
  152. {
  153. public:
  154. DnDFrame();
  155. virtual ~DnDFrame();
  156. void OnPaint(wxPaintEvent& event);
  157. void OnSize(wxSizeEvent& event);
  158. void OnQuit(wxCommandEvent& event);
  159. void OnAbout(wxCommandEvent& event);
  160. void OnDrag(wxCommandEvent& event);
  161. void OnDragMoveByDefault(wxCommandEvent& event);
  162. void OnDragMoveAllow(wxCommandEvent& event);
  163. void OnNewFrame(wxCommandEvent& event);
  164. void OnHelp (wxCommandEvent& event);
  165. #if wxUSE_LOG
  166. void OnLogClear(wxCommandEvent& event);
  167. #endif // wxUSE_LOG
  168. void OnCopy(wxCommandEvent& event);
  169. void OnPaste(wxCommandEvent& event);
  170. void OnCopyBitmap(wxCommandEvent& event);
  171. void OnPasteBitmap(wxCommandEvent& event);
  172. #if wxUSE_METAFILE
  173. void OnPasteMetafile(wxCommandEvent& event);
  174. #endif // wxUSE_METAFILE
  175. void OnCopyFiles(wxCommandEvent& event);
  176. void OnCopyURL(wxCommandEvent& event);
  177. void OnUsePrimary(wxCommandEvent& event);
  178. void OnLeftDown(wxMouseEvent& event);
  179. void OnRightDown(wxMouseEvent& event);
  180. #if wxUSE_DRAG_AND_DROP
  181. void OnBeginDrag(wxTreeEvent& event);
  182. #endif // wxUSE_DRAG_AND_DROP
  183. void OnUpdateUIMoveByDefault(wxUpdateUIEvent& event);
  184. void OnUpdateUIPasteText(wxUpdateUIEvent& event);
  185. void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
  186. private:
  187. #if wxUSE_DRAG_AND_DROP
  188. // show the result of a dnd operation in the status bar
  189. void LogDragResult(wxDragResult result);
  190. #endif // wxUSE_DRAG_AND_DROP
  191. // GUI controls
  192. wxListBox *m_ctrlFile,
  193. *m_ctrlText;
  194. wxGenericDirCtrl *m_ctrlDir;
  195. #if wxUSE_LOG
  196. wxTextCtrl *m_ctrlLog;
  197. wxLog *m_pLog,
  198. *m_pLogPrev;
  199. #endif // wxUSE_LOG
  200. // move the text by default (or copy)?
  201. bool m_moveByDefault;
  202. // allow moving the text at all?
  203. bool m_moveAllow;
  204. // the text we drag
  205. wxString m_strText;
  206. wxDECLARE_EVENT_TABLE();
  207. };
  208. // ----------------------------------------------------------------------------
  209. // A shape is an example of application-specific data which may be transported
  210. // via drag-and-drop or clipboard: in our case, we have different geometric
  211. // shapes, each one with its own colour and position
  212. // ----------------------------------------------------------------------------
  213. #if wxUSE_DRAG_AND_DROP
  214. class DnDShape
  215. {
  216. public:
  217. enum Kind
  218. {
  219. None,
  220. Triangle,
  221. Rectangle,
  222. Ellipse
  223. };
  224. DnDShape(const wxPoint& pos,
  225. const wxSize& size,
  226. const wxColour& col)
  227. : m_pos(pos), m_size(size), m_col(col)
  228. {
  229. }
  230. // this is for debugging - lets us see when exactly an object is freed
  231. // (this may be later than you think if it's on the clipboard, for example)
  232. virtual ~DnDShape() { }
  233. // the functions used for drag-and-drop: they dump and restore a shape into
  234. // some bitwise-copiable data (might use streams too...)
  235. // ------------------------------------------------------------------------
  236. // restore from buffer
  237. static DnDShape *New(const void *buf);
  238. virtual size_t GetDataSize() const
  239. {
  240. return sizeof(ShapeDump);
  241. }
  242. virtual void GetDataHere(void *buf) const
  243. {
  244. ShapeDump& dump = *(ShapeDump *)buf;
  245. dump.x = m_pos.x;
  246. dump.y = m_pos.y;
  247. dump.w = m_size.x;
  248. dump.h = m_size.y;
  249. dump.r = m_col.Red();
  250. dump.g = m_col.Green();
  251. dump.b = m_col.Blue();
  252. dump.k = GetKind();
  253. }
  254. // accessors
  255. const wxPoint& GetPosition() const { return m_pos; }
  256. const wxColour& GetColour() const { return m_col; }
  257. const wxSize& GetSize() const { return m_size; }
  258. void Move(const wxPoint& pos) { m_pos = pos; }
  259. // to implement in derived classes
  260. virtual Kind GetKind() const = 0;
  261. virtual void Draw(wxDC& dc)
  262. {
  263. dc.SetPen(wxPen(m_col));
  264. }
  265. protected:
  266. //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
  267. wxPoint GetCentre() const
  268. { return wxPoint(m_pos.x + m_size.x / 2 - 1, m_pos.y + m_size.y / 2 - 1); }
  269. struct ShapeDump
  270. {
  271. wxCoord x, y, // position
  272. w, h; // size
  273. int k; // kind
  274. unsigned char r, g, b; // colour
  275. };
  276. wxPoint m_pos;
  277. wxSize m_size;
  278. wxColour m_col;
  279. };
  280. class DnDTriangularShape : public DnDShape
  281. {
  282. public:
  283. DnDTriangularShape(const wxPoint& pos,
  284. const wxSize& size,
  285. const wxColour& col)
  286. : DnDShape(pos, size, col)
  287. {
  288. wxLogMessage(wxT("DnDTriangularShape is being created"));
  289. }
  290. virtual ~DnDTriangularShape()
  291. {
  292. wxLogMessage(wxT("DnDTriangularShape is being deleted"));
  293. }
  294. virtual Kind GetKind() const { return Triangle; }
  295. virtual void Draw(wxDC& dc)
  296. {
  297. DnDShape::Draw(dc);
  298. // well, it's a bit difficult to describe a triangle by position and
  299. // size, but we're not doing geometry here, do we? ;-)
  300. wxPoint p1(m_pos);
  301. wxPoint p2(m_pos.x + m_size.x, m_pos.y);
  302. wxPoint p3(m_pos.x, m_pos.y + m_size.y);
  303. dc.DrawLine(p1, p2);
  304. dc.DrawLine(p2, p3);
  305. dc.DrawLine(p3, p1);
  306. //works in multicolor modes; on GTK (at least) will fail in 16-bit color
  307. dc.SetBrush(wxBrush(m_col));
  308. dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
  309. }
  310. };
  311. class DnDRectangularShape : public DnDShape
  312. {
  313. public:
  314. DnDRectangularShape(const wxPoint& pos,
  315. const wxSize& size,
  316. const wxColour& col)
  317. : DnDShape(pos, size, col)
  318. {
  319. wxLogMessage(wxT("DnDRectangularShape is being created"));
  320. }
  321. virtual ~DnDRectangularShape()
  322. {
  323. wxLogMessage(wxT("DnDRectangularShape is being deleted"));
  324. }
  325. virtual Kind GetKind() const { return Rectangle; }
  326. virtual void Draw(wxDC& dc)
  327. {
  328. DnDShape::Draw(dc);
  329. wxPoint p1(m_pos);
  330. wxPoint p2(p1.x + m_size.x, p1.y);
  331. wxPoint p3(p2.x, p2.y + m_size.y);
  332. wxPoint p4(p1.x, p3.y);
  333. dc.DrawLine(p1, p2);
  334. dc.DrawLine(p2, p3);
  335. dc.DrawLine(p3, p4);
  336. dc.DrawLine(p4, p1);
  337. dc.SetBrush(wxBrush(m_col));
  338. dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
  339. }
  340. };
  341. class DnDEllipticShape : public DnDShape
  342. {
  343. public:
  344. DnDEllipticShape(const wxPoint& pos,
  345. const wxSize& size,
  346. const wxColour& col)
  347. : DnDShape(pos, size, col)
  348. {
  349. wxLogMessage(wxT("DnDEllipticShape is being created"));
  350. }
  351. virtual ~DnDEllipticShape()
  352. {
  353. wxLogMessage(wxT("DnDEllipticShape is being deleted"));
  354. }
  355. virtual Kind GetKind() const { return Ellipse; }
  356. virtual void Draw(wxDC& dc)
  357. {
  358. DnDShape::Draw(dc);
  359. dc.DrawEllipse(m_pos, m_size);
  360. dc.SetBrush(wxBrush(m_col));
  361. dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
  362. }
  363. };
  364. // ----------------------------------------------------------------------------
  365. // A wxDataObject specialisation for the application-specific data
  366. // ----------------------------------------------------------------------------
  367. static const wxChar *shapeFormatId = wxT("wxShape");
  368. class DnDShapeDataObject : public wxDataObject
  369. {
  370. public:
  371. // ctor doesn't copy the pointer, so it shouldn't go away while this object
  372. // is alive
  373. DnDShapeDataObject(DnDShape *shape = (DnDShape *)NULL)
  374. {
  375. if ( shape )
  376. {
  377. // we need to copy the shape because the one we're handled may be
  378. // deleted while it's still on the clipboard (for example) - and we
  379. // reuse the serialisation methods here to copy it
  380. void *buf = malloc(shape->DnDShape::GetDataSize());
  381. shape->GetDataHere(buf);
  382. m_shape = DnDShape::New(buf);
  383. free(buf);
  384. }
  385. else
  386. {
  387. // nothing to copy
  388. m_shape = NULL;
  389. }
  390. // this string should uniquely identify our format, but is otherwise
  391. // arbitrary
  392. m_formatShape.SetId(shapeFormatId);
  393. // we don't draw the shape to a bitmap until it's really needed (i.e.
  394. // we're asked to do so)
  395. m_hasBitmap = false;
  396. #if wxUSE_METAFILE
  397. m_hasMetaFile = false;
  398. #endif // wxUSE_METAFILE
  399. }
  400. virtual ~DnDShapeDataObject() { delete m_shape; }
  401. // after a call to this function, the shape is owned by the caller and it
  402. // is responsible for deleting it!
  403. //
  404. // NB: a better solution would be to make DnDShapes ref counted and this
  405. // is what should probably be done in a real life program, otherwise
  406. // the ownership problems become too complicated really fast
  407. DnDShape *GetShape()
  408. {
  409. DnDShape *shape = m_shape;
  410. m_shape = (DnDShape *)NULL;
  411. m_hasBitmap = false;
  412. #if wxUSE_METAFILE
  413. m_hasMetaFile = false;
  414. #endif // wxUSE_METAFILE
  415. return shape;
  416. }
  417. // implement base class pure virtuals
  418. // ----------------------------------
  419. virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const
  420. {
  421. return m_formatShape;
  422. }
  423. virtual size_t GetFormatCount(Direction dir) const
  424. {
  425. // our custom format is supported by both GetData() and SetData()
  426. size_t nFormats = 1;
  427. if ( dir == Get )
  428. {
  429. // but the bitmap format(s) are only supported for output
  430. nFormats += m_dobjBitmap.GetFormatCount(dir);
  431. #if wxUSE_METAFILE
  432. nFormats += m_dobjMetaFile.GetFormatCount(dir);
  433. #endif // wxUSE_METAFILE
  434. }
  435. return nFormats;
  436. }
  437. virtual void GetAllFormats(wxDataFormat *formats, Direction dir) const
  438. {
  439. formats[0] = m_formatShape;
  440. if ( dir == Get )
  441. {
  442. // in Get direction we additionally support bitmaps and metafiles
  443. // under Windows
  444. m_dobjBitmap.GetAllFormats(&formats[1], dir);
  445. #if wxUSE_METAFILE
  446. // don't assume that m_dobjBitmap has only 1 format
  447. m_dobjMetaFile.GetAllFormats(&formats[1 +
  448. m_dobjBitmap.GetFormatCount(dir)], dir);
  449. #endif // wxUSE_METAFILE
  450. }
  451. }
  452. virtual size_t GetDataSize(const wxDataFormat& format) const
  453. {
  454. if ( format == m_formatShape )
  455. {
  456. return m_shape->GetDataSize();
  457. }
  458. #if wxUSE_METAFILE
  459. else if ( m_dobjMetaFile.IsSupported(format) )
  460. {
  461. if ( !m_hasMetaFile )
  462. CreateMetaFile();
  463. return m_dobjMetaFile.GetDataSize(format);
  464. }
  465. #endif // wxUSE_METAFILE
  466. else
  467. {
  468. wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
  469. wxT("unexpected format") );
  470. if ( !m_hasBitmap )
  471. CreateBitmap();
  472. return m_dobjBitmap.GetDataSize();
  473. }
  474. }
  475. virtual bool GetDataHere(const wxDataFormat& format, void *pBuf) const
  476. {
  477. if ( format == m_formatShape )
  478. {
  479. m_shape->GetDataHere(pBuf);
  480. return true;
  481. }
  482. #if wxUSE_METAFILE
  483. else if ( m_dobjMetaFile.IsSupported(format) )
  484. {
  485. if ( !m_hasMetaFile )
  486. CreateMetaFile();
  487. return m_dobjMetaFile.GetDataHere(format, pBuf);
  488. }
  489. #endif // wxUSE_METAFILE
  490. else
  491. {
  492. wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
  493. wxT("unexpected format") );
  494. if ( !m_hasBitmap )
  495. CreateBitmap();
  496. return m_dobjBitmap.GetDataHere(pBuf);
  497. }
  498. }
  499. virtual bool SetData(const wxDataFormat& format,
  500. size_t WXUNUSED(len), const void *buf)
  501. {
  502. wxCHECK_MSG( format == m_formatShape, false,
  503. wxT( "unsupported format") );
  504. delete m_shape;
  505. m_shape = DnDShape::New(buf);
  506. // the shape has changed
  507. m_hasBitmap = false;
  508. #if wxUSE_METAFILE
  509. m_hasMetaFile = false;
  510. #endif // wxUSE_METAFILE
  511. return true;
  512. }
  513. private:
  514. // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
  515. void CreateBitmap() const;
  516. #if wxUSE_METAFILE
  517. void CreateMetaFile() const;
  518. #endif // wxUSE_METAFILE
  519. wxDataFormat m_formatShape; // our custom format
  520. wxBitmapDataObject m_dobjBitmap; // it handles bitmaps
  521. bool m_hasBitmap; // true if m_dobjBitmap has valid bitmap
  522. #if wxUSE_METAFILE
  523. wxMetaFileDataObject m_dobjMetaFile;// handles metafiles
  524. bool m_hasMetaFile; // true if we have valid metafile
  525. #endif // wxUSE_METAFILE
  526. DnDShape *m_shape; // our data
  527. };
  528. // ----------------------------------------------------------------------------
  529. // A dialog to edit shape properties
  530. // ----------------------------------------------------------------------------
  531. class DnDShapeDialog : public wxDialog
  532. {
  533. public:
  534. DnDShapeDialog(wxFrame *parent, DnDShape *shape);
  535. DnDShape *GetShape() const;
  536. virtual bool TransferDataToWindow();
  537. virtual bool TransferDataFromWindow();
  538. void OnColour(wxCommandEvent& event);
  539. private:
  540. // input
  541. DnDShape *m_shape;
  542. // output
  543. DnDShape::Kind m_shapeKind;
  544. wxPoint m_pos;
  545. wxSize m_size;
  546. wxColour m_col;
  547. // controls
  548. wxRadioBox *m_radio;
  549. wxTextCtrl *m_textX,
  550. *m_textY,
  551. *m_textW,
  552. *m_textH;
  553. wxDECLARE_EVENT_TABLE();
  554. };
  555. // ----------------------------------------------------------------------------
  556. // A frame for the shapes which can be drag-and-dropped between frames
  557. // ----------------------------------------------------------------------------
  558. class DnDShapeFrame : public wxFrame
  559. {
  560. public:
  561. DnDShapeFrame(wxFrame *parent);
  562. ~DnDShapeFrame();
  563. void SetShape(DnDShape *shape);
  564. virtual bool SetShape(const wxRegion &region)
  565. {
  566. return wxFrame::SetShape( region );
  567. }
  568. // callbacks
  569. void OnNewShape(wxCommandEvent& event);
  570. void OnEditShape(wxCommandEvent& event);
  571. void OnClearShape(wxCommandEvent& event);
  572. void OnCopyShape(wxCommandEvent& event);
  573. void OnPasteShape(wxCommandEvent& event);
  574. void OnUpdateUICopy(wxUpdateUIEvent& event);
  575. void OnUpdateUIPaste(wxUpdateUIEvent& event);
  576. void OnDrag(wxMouseEvent& event);
  577. void OnPaint(wxPaintEvent& event);
  578. void OnDrop(wxCoord x, wxCoord y, DnDShape *shape);
  579. private:
  580. DnDShape *m_shape;
  581. static DnDShapeFrame *ms_lastDropTarget;
  582. wxDECLARE_EVENT_TABLE();
  583. };
  584. // ----------------------------------------------------------------------------
  585. // wxDropTarget derivation for DnDShapes
  586. // ----------------------------------------------------------------------------
  587. class DnDShapeDropTarget : public wxDropTarget
  588. {
  589. public:
  590. DnDShapeDropTarget(DnDShapeFrame *frame)
  591. : wxDropTarget(new DnDShapeDataObject)
  592. {
  593. m_frame = frame;
  594. }
  595. // override base class (pure) virtuals
  596. virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def)
  597. {
  598. #if wxUSE_STATUSBAR
  599. m_frame->SetStatusText(wxT("Mouse entered the frame"));
  600. #endif // wxUSE_STATUSBAR
  601. return OnDragOver(x, y, def);
  602. }
  603. virtual void OnLeave()
  604. {
  605. #if wxUSE_STATUSBAR
  606. m_frame->SetStatusText(wxT("Mouse left the frame"));
  607. #endif // wxUSE_STATUSBAR
  608. }
  609. virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
  610. {
  611. if ( !GetData() )
  612. {
  613. wxLogError(wxT("Failed to get drag and drop data"));
  614. return wxDragNone;
  615. }
  616. m_frame->OnDrop(x, y,
  617. ((DnDShapeDataObject *)GetDataObject())->GetShape());
  618. return def;
  619. }
  620. private:
  621. DnDShapeFrame *m_frame;
  622. };
  623. #endif // wxUSE_DRAG_AND_DROP
  624. // ----------------------------------------------------------------------------
  625. // functions prototypes
  626. // ----------------------------------------------------------------------------
  627. static void ShowBitmap(const wxBitmap& bitmap);
  628. #if wxUSE_METAFILE
  629. static void ShowMetaFile(const wxMetaFile& metafile);
  630. #endif // wxUSE_METAFILE
  631. // ----------------------------------------------------------------------------
  632. // IDs for the menu commands
  633. // ----------------------------------------------------------------------------
  634. enum
  635. {
  636. Menu_Quit = 1,
  637. Menu_Drag,
  638. Menu_DragMoveDef,
  639. Menu_DragMoveAllow,
  640. Menu_NewFrame,
  641. Menu_About = 101,
  642. Menu_Help,
  643. Menu_Clear,
  644. Menu_Copy,
  645. Menu_Paste,
  646. Menu_CopyBitmap,
  647. Menu_PasteBitmap,
  648. Menu_PasteMFile,
  649. Menu_CopyFiles,
  650. Menu_CopyURL,
  651. Menu_UsePrimary,
  652. Menu_Shape_New = 500,
  653. Menu_Shape_Edit,
  654. Menu_Shape_Clear,
  655. Menu_ShapeClipboard_Copy,
  656. Menu_ShapeClipboard_Paste,
  657. Button_Colour = 1001
  658. };
  659. wxBEGIN_EVENT_TABLE(DnDFrame, wxFrame)
  660. EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
  661. EVT_MENU(Menu_About, DnDFrame::OnAbout)
  662. EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
  663. EVT_MENU(Menu_DragMoveDef, DnDFrame::OnDragMoveByDefault)
  664. EVT_MENU(Menu_DragMoveAllow,DnDFrame::OnDragMoveAllow)
  665. EVT_MENU(Menu_NewFrame, DnDFrame::OnNewFrame)
  666. EVT_MENU(Menu_Help, DnDFrame::OnHelp)
  667. #if wxUSE_LOG
  668. EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
  669. #endif // wxUSE_LOG
  670. EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
  671. EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
  672. EVT_MENU(Menu_CopyBitmap, DnDFrame::OnCopyBitmap)
  673. EVT_MENU(Menu_PasteBitmap,DnDFrame::OnPasteBitmap)
  674. #if wxUSE_METAFILE
  675. EVT_MENU(Menu_PasteMFile, DnDFrame::OnPasteMetafile)
  676. #endif // wxUSE_METAFILE
  677. EVT_MENU(Menu_CopyFiles, DnDFrame::OnCopyFiles)
  678. EVT_MENU(Menu_CopyURL, DnDFrame::OnCopyURL)
  679. EVT_MENU(Menu_UsePrimary, DnDFrame::OnUsePrimary)
  680. EVT_UPDATE_UI(Menu_DragMoveDef, DnDFrame::OnUpdateUIMoveByDefault)
  681. EVT_UPDATE_UI(Menu_Paste, DnDFrame::OnUpdateUIPasteText)
  682. EVT_UPDATE_UI(Menu_PasteBitmap, DnDFrame::OnUpdateUIPasteBitmap)
  683. EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
  684. EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
  685. EVT_PAINT( DnDFrame::OnPaint)
  686. EVT_SIZE( DnDFrame::OnSize)
  687. wxEND_EVENT_TABLE()
  688. #if wxUSE_DRAG_AND_DROP
  689. wxBEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
  690. EVT_MENU(Menu_Shape_New, DnDShapeFrame::OnNewShape)
  691. EVT_MENU(Menu_Shape_Edit, DnDShapeFrame::OnEditShape)
  692. EVT_MENU(Menu_Shape_Clear, DnDShapeFrame::OnClearShape)
  693. EVT_MENU(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnCopyShape)
  694. EVT_MENU(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnPasteShape)
  695. EVT_UPDATE_UI(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnUpdateUICopy)
  696. EVT_UPDATE_UI(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnUpdateUIPaste)
  697. EVT_LEFT_DOWN(DnDShapeFrame::OnDrag)
  698. EVT_PAINT(DnDShapeFrame::OnPaint)
  699. wxEND_EVENT_TABLE()
  700. wxBEGIN_EVENT_TABLE(DnDShapeDialog, wxDialog)
  701. EVT_BUTTON(Button_Colour, DnDShapeDialog::OnColour)
  702. wxEND_EVENT_TABLE()
  703. #endif // wxUSE_DRAG_AND_DROP
  704. wxBEGIN_EVENT_TABLE(DnDCanvasBitmap, wxScrolledWindow)
  705. EVT_PAINT(DnDCanvasBitmap::OnPaint)
  706. wxEND_EVENT_TABLE()
  707. #if wxUSE_METAFILE
  708. wxBEGIN_EVENT_TABLE(DnDCanvasMetafile, wxScrolledWindow)
  709. EVT_PAINT(DnDCanvasMetafile::OnPaint)
  710. wxEND_EVENT_TABLE()
  711. #endif // wxUSE_METAFILE
  712. #endif // wxUSE_DRAG_AND_DROP
  713. // ============================================================================
  714. // implementation
  715. // ============================================================================
  716. // `Main program' equivalent, creating windows and returning main app frame
  717. bool DnDApp::OnInit()
  718. {
  719. if ( !wxApp::OnInit() )
  720. return false;
  721. #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
  722. // switch on trace messages
  723. #if wxUSE_LOG
  724. #if defined(__WXGTK__)
  725. wxLog::AddTraceMask(wxT("clipboard"));
  726. #elif defined(__WXMSW__)
  727. wxLog::AddTraceMask(wxTRACE_OleCalls);
  728. #endif
  729. #endif // wxUSE_LOG
  730. #if wxUSE_LIBPNG
  731. wxImage::AddHandler( new wxPNGHandler );
  732. #endif
  733. // create the main frame window
  734. new DnDFrame();
  735. return true;
  736. #else
  737. wxMessageBox( wxT("This sample has to be compiled with wxUSE_DRAG_AND_DROP"), wxT("Building error"), wxOK);
  738. return false;
  739. #endif // wxUSE_DRAG_AND_DROP
  740. }
  741. #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
  742. DnDFrame::DnDFrame()
  743. : wxFrame(NULL, wxID_ANY, wxT("Drag-and-Drop/Clipboard wxWidgets Sample"),
  744. wxPoint(10, 100)),
  745. m_strText(wxT("wxWidgets drag & drop works :-)"))
  746. {
  747. // frame icon and status bar
  748. SetIcon(wxICON(sample));
  749. #if wxUSE_STATUSBAR
  750. CreateStatusBar();
  751. #endif // wxUSE_STATUSBAR
  752. // construct menu
  753. wxMenu *file_menu = new wxMenu;
  754. file_menu->Append(Menu_Drag, wxT("&Test drag..."));
  755. file_menu->AppendCheckItem(Menu_DragMoveDef, wxT("&Move by default"));
  756. file_menu->AppendCheckItem(Menu_DragMoveAllow, wxT("&Allow moving"));
  757. file_menu->AppendSeparator();
  758. file_menu->Append(Menu_NewFrame, wxT("&New frame\tCtrl-N"));
  759. file_menu->AppendSeparator();
  760. file_menu->Append(Menu_Quit, wxT("E&xit\tCtrl-Q"));
  761. #if wxUSE_LOG
  762. wxMenu *log_menu = new wxMenu;
  763. log_menu->Append(Menu_Clear, wxT("Clear\tCtrl-L"));
  764. #endif // wxUSE_LOG
  765. wxMenu *help_menu = new wxMenu;
  766. help_menu->Append(Menu_Help, wxT("&Help..."));
  767. help_menu->AppendSeparator();
  768. help_menu->Append(Menu_About, wxT("&About"));
  769. wxMenu *clip_menu = new wxMenu;
  770. clip_menu->Append(Menu_Copy, wxT("&Copy text\tCtrl-C"));
  771. clip_menu->Append(Menu_Paste, wxT("&Paste text\tCtrl-V"));
  772. clip_menu->AppendSeparator();
  773. clip_menu->Append(Menu_CopyBitmap, wxT("Copy &bitmap\tCtrl-Shift-C"));
  774. clip_menu->Append(Menu_PasteBitmap, wxT("Paste b&itmap\tCtrl-Shift-V"));
  775. #if wxUSE_METAFILE
  776. clip_menu->AppendSeparator();
  777. clip_menu->Append(Menu_PasteMFile, wxT("Paste &metafile\tCtrl-M"));
  778. #endif // wxUSE_METAFILE
  779. clip_menu->AppendSeparator();
  780. clip_menu->Append(Menu_CopyFiles, wxT("Copy &files\tCtrl-F"));
  781. clip_menu->Append(Menu_CopyURL, wxT("Copy &URL\tCtrl-U"));
  782. clip_menu->AppendSeparator();
  783. clip_menu->AppendCheckItem(Menu_UsePrimary, wxT("Use &primary selection\tCtrl-P"));
  784. wxMenuBar *menu_bar = new wxMenuBar;
  785. menu_bar->Append(file_menu, wxT("&File"));
  786. #if wxUSE_LOG
  787. menu_bar->Append(log_menu, wxT("&Log"));
  788. #endif // wxUSE_LOG
  789. menu_bar->Append(clip_menu, wxT("&Clipboard"));
  790. menu_bar->Append(help_menu, wxT("&Help"));
  791. SetMenuBar(menu_bar);
  792. // create the child controls
  793. SetBackgroundColour(*wxWHITE); // labels read better on this background
  794. wxString strFile(wxT("Drop files here!")), strText(wxT("Drop text on me"));
  795. m_ctrlFile = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, &strFile,
  796. wxLB_HSCROLL | wxLB_ALWAYS_SB );
  797. m_ctrlText = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, &strText,
  798. wxLB_HSCROLL | wxLB_ALWAYS_SB );
  799. m_ctrlDir = new wxGenericDirCtrl(this);
  800. #if wxUSE_LOG
  801. m_ctrlLog = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
  802. wxDefaultPosition, wxDefaultSize,
  803. wxTE_MULTILINE | wxTE_READONLY |
  804. wxSUNKEN_BORDER );
  805. // redirect log messages to the text window
  806. m_pLog = new wxLogTextCtrl(m_ctrlLog);
  807. m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
  808. #endif // wxUSE_LOG
  809. #if wxUSE_DRAG_AND_DROP
  810. // associate drop targets with the controls
  811. m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
  812. m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
  813. #if wxUSE_DRAG_AND_DROP
  814. m_ctrlDir->Connect
  815. (
  816. wxID_ANY,
  817. wxEVT_TREE_BEGIN_DRAG,
  818. wxTreeEventHandler(DnDFrame::OnBeginDrag),
  819. NULL,
  820. this
  821. );
  822. #endif // wxUSE_DRAG_AND_DROP
  823. #if wxUSE_LOG
  824. m_ctrlLog->SetDropTarget(new URLDropTarget);
  825. #endif // wxUSE_LOG
  826. #endif // wxUSE_DRAG_AND_DROP
  827. wxBoxSizer *sizer_top = new wxBoxSizer( wxHORIZONTAL );
  828. sizer_top->Add(m_ctrlFile, 1, wxEXPAND );
  829. sizer_top->Add(m_ctrlText, 1, wxEXPAND );
  830. wxBoxSizer *sizerDirCtrl = new wxBoxSizer(wxVERTICAL);
  831. sizerDirCtrl->Add(new wxStaticText(this, wxID_ANY, "Drag files from here"),
  832. wxSizerFlags().Centre().Border());
  833. sizerDirCtrl->Add(m_ctrlDir, wxSizerFlags(1).Expand());
  834. sizer_top->Add(sizerDirCtrl, 1, wxEXPAND );
  835. // make all columns of reasonable minimal size
  836. for ( unsigned n = 0; n < sizer_top->GetChildren().size(); n++ )
  837. sizer_top->SetItemMinSize(n, 200, 300);
  838. wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
  839. sizer->Add(sizer_top, 1, wxEXPAND );
  840. #if wxUSE_LOG
  841. sizer->Add(m_ctrlLog, 2, wxEXPAND);
  842. sizer->SetItemMinSize(m_ctrlLog, 450, 200);
  843. #endif // wxUSE_LOG
  844. sizer->AddSpacer(50);
  845. // copy data by default but allow moving it as well
  846. m_moveByDefault = false;
  847. m_moveAllow = true;
  848. menu_bar->Check(Menu_DragMoveAllow, true);
  849. // set the correct size and show the frame
  850. SetSizerAndFit(sizer);
  851. Show();
  852. }
  853. void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  854. {
  855. Close(true);
  856. }
  857. void DnDFrame::OnSize(wxSizeEvent& event)
  858. {
  859. Refresh();
  860. event.Skip();
  861. }
  862. void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
  863. {
  864. int w = 0;
  865. int h = 0;
  866. GetClientSize( &w, &h );
  867. wxPaintDC dc(this);
  868. // dc.Clear(); -- this kills wxGTK
  869. dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, false, wxT("charter") ) );
  870. dc.DrawText( wxT("Drag text from here!"), 100, h-50 );
  871. }
  872. void DnDFrame::OnUpdateUIMoveByDefault(wxUpdateUIEvent& event)
  873. {
  874. // only can move by default if moving is allowed at all
  875. event.Enable(m_moveAllow);
  876. }
  877. void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
  878. {
  879. #ifdef __WXDEBUG__
  880. // too many trace messages if we don't do it - this function is called
  881. // very often
  882. wxLogNull nolog;
  883. #endif
  884. event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
  885. }
  886. void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
  887. {
  888. #ifdef __WXDEBUG__
  889. // too many trace messages if we don't do it - this function is called
  890. // very often
  891. wxLogNull nolog;
  892. #endif
  893. event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
  894. }
  895. void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
  896. {
  897. #if wxUSE_DRAG_AND_DROP
  898. (new DnDShapeFrame(this))->Show(true);
  899. wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
  900. #endif // wxUSE_DRAG_AND_DROP
  901. }
  902. void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
  903. {
  904. #if wxUSE_DRAG_AND_DROP
  905. wxString strText = wxGetTextFromUser
  906. (
  907. wxT("After you enter text in this dialog, press any mouse\n")
  908. wxT("button in the bottom (empty) part of the frame and \n")
  909. wxT("drag it anywhere - you will be in fact dragging the\n")
  910. wxT("text object containing this text"),
  911. wxT("Please enter some text"), m_strText, this
  912. );
  913. m_strText = strText;
  914. #endif // wxUSE_DRAG_AND_DROP
  915. }
  916. void DnDFrame::OnDragMoveByDefault(wxCommandEvent& event)
  917. {
  918. m_moveByDefault = event.IsChecked();
  919. }
  920. void DnDFrame::OnDragMoveAllow(wxCommandEvent& event)
  921. {
  922. m_moveAllow = event.IsChecked();
  923. }
  924. void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  925. {
  926. wxMessageBox(wxT("Drag-&-Drop Demo\n")
  927. wxT("Please see \"Help|Help...\" for details\n")
  928. wxT("Copyright (c) 1998 Vadim Zeitlin"),
  929. wxT("About wxDnD"),
  930. wxICON_INFORMATION | wxOK,
  931. this);
  932. }
  933. void DnDFrame::OnHelp(wxCommandEvent& /* event */)
  934. {
  935. wxMessageDialog dialog(this,
  936. wxT("This small program demonstrates drag & drop support in wxWidgets. The program window\n")
  937. wxT("consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n")
  938. wxT("going on inside. The top part is split into 2 listboxes, the left one accepts files\n")
  939. wxT("and the right one accepts text.\n")
  940. wxT("\n")
  941. wxT("To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n")
  942. wxT("the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n")
  943. wxT("Also, try dragging some files (you can select several at once) from Windows Explorer (or \n")
  944. wxT("File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n")
  945. wxT("work with files) and see what changes.\n")
  946. wxT("\n")
  947. wxT("To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n")
  948. wxT("it to wordpad or any other droptarget accepting text (and of course you can just drag it\n")
  949. wxT("to the right pane). Due to a lot of trace messages, the cursor might take some time to \n")
  950. wxT("change, don't release the mouse button until it does. You can change the string being\n")
  951. wxT("dragged in \"File|Test drag...\" dialog.\n")
  952. wxT("\n")
  953. wxT("\n")
  954. wxT("Please send all questions/bug reports/suggestions &c to \n")
  955. wxT("Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>"),
  956. wxT("wxDnD Help"));
  957. dialog.ShowModal();
  958. }
  959. #if wxUSE_LOG
  960. void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
  961. {
  962. m_ctrlLog->Clear();
  963. m_ctrlText->Clear();
  964. m_ctrlFile->Clear();
  965. }
  966. #endif // wxUSE_LOG
  967. #if wxUSE_DRAG_AND_DROP
  968. void DnDFrame::LogDragResult(wxDragResult result)
  969. {
  970. #if wxUSE_STATUSBAR
  971. const wxChar *pc;
  972. switch ( result )
  973. {
  974. case wxDragError: pc = wxT("Error!"); break;
  975. case wxDragNone: pc = wxT("Nothing"); break;
  976. case wxDragCopy: pc = wxT("Copied"); break;
  977. case wxDragMove: pc = wxT("Moved"); break;
  978. case wxDragCancel: pc = wxT("Cancelled"); break;
  979. default: pc = wxT("Huh?"); break;
  980. }
  981. SetStatusText(wxString(wxT("Drag result: ")) + pc);
  982. #else
  983. wxUnusedVar(result);
  984. #endif // wxUSE_STATUSBAR
  985. }
  986. #endif // wxUSE_DRAG_AND_DROP
  987. void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
  988. {
  989. #if wxUSE_DRAG_AND_DROP
  990. if ( !m_strText.empty() )
  991. {
  992. // start drag operation
  993. wxTextDataObject textData(m_strText);
  994. wxDropSource source(textData, this,
  995. wxDROP_ICON(dnd_copy),
  996. wxDROP_ICON(dnd_move),
  997. wxDROP_ICON(dnd_none));
  998. int flags = 0;
  999. if ( m_moveByDefault )
  1000. flags |= wxDrag_DefaultMove;
  1001. else if ( m_moveAllow )
  1002. flags |= wxDrag_AllowMove;
  1003. LogDragResult(source.DoDragDrop(flags));
  1004. }
  1005. #endif // wxUSE_DRAG_AND_DROP
  1006. }
  1007. void DnDFrame::OnRightDown(wxMouseEvent &event )
  1008. {
  1009. wxMenu menu(wxT("Dnd sample menu"));
  1010. menu.Append(Menu_Drag, wxT("&Test drag..."));
  1011. menu.AppendSeparator();
  1012. menu.Append(Menu_About, wxT("&About"));
  1013. PopupMenu( &menu, event.GetX(), event.GetY() );
  1014. }
  1015. DnDFrame::~DnDFrame()
  1016. {
  1017. #if wxUSE_LOG
  1018. if ( m_pLog != NULL ) {
  1019. if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
  1020. delete m_pLog;
  1021. }
  1022. #endif // wxUSE_LOG
  1023. }
  1024. void DnDFrame::OnUsePrimary(wxCommandEvent& event)
  1025. {
  1026. const bool usePrimary = event.IsChecked();
  1027. wxTheClipboard->UsePrimarySelection(usePrimary);
  1028. wxLogStatus(wxT("Now using %s selection"), usePrimary ? wxT("primary")
  1029. : wxT("clipboard"));
  1030. }
  1031. #if wxUSE_DRAG_AND_DROP
  1032. void DnDFrame::OnBeginDrag(wxTreeEvent& WXUNUSED(event))
  1033. {
  1034. wxFileDataObject data;
  1035. data.AddFile(m_ctrlDir->GetPath());
  1036. wxDropSource dragSource(this);
  1037. dragSource.SetData(data);
  1038. LogDragResult(dragSource.DoDragDrop());
  1039. }
  1040. #endif // wxUSE_DRAG_AND_DROP
  1041. // ---------------------------------------------------------------------------
  1042. // bitmap clipboard
  1043. // ---------------------------------------------------------------------------
  1044. void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
  1045. {
  1046. // PNG support is not always compiled in under Windows, so use BMP there
  1047. #if wxUSE_LIBPNG
  1048. wxFileDialog dialog(this, wxT("Open a PNG file"), wxEmptyString, wxEmptyString, wxT("PNG files (*.png)|*.png"), 0);
  1049. #else
  1050. wxFileDialog dialog(this, wxT("Open a BMP file"), wxEmptyString, wxEmptyString, wxT("BMP files (*.bmp)|*.bmp"), 0);
  1051. #endif
  1052. if (dialog.ShowModal() != wxID_OK)
  1053. {
  1054. wxLogMessage( wxT("Aborted file open") );
  1055. return;
  1056. }
  1057. if (dialog.GetPath().empty())
  1058. {
  1059. wxLogMessage( wxT("Returned empty string.") );
  1060. return;
  1061. }
  1062. if (!wxFileExists(dialog.GetPath()))
  1063. {
  1064. wxLogMessage( wxT("File doesn't exist.") );
  1065. return;
  1066. }
  1067. wxImage image;
  1068. image.LoadFile( dialog.GetPath(),
  1069. #if wxUSE_LIBPNG
  1070. wxBITMAP_TYPE_PNG
  1071. #else
  1072. wxBITMAP_TYPE_BMP
  1073. #endif
  1074. );
  1075. if (!image.IsOk())
  1076. {
  1077. wxLogError( wxT("Invalid image file...") );
  1078. return;
  1079. }
  1080. wxLogStatus( wxT("Decoding image file...") );
  1081. wxYield();
  1082. wxBitmap bitmap( image );
  1083. if ( !wxTheClipboard->Open() )
  1084. {
  1085. wxLogError(wxT("Can't open clipboard."));
  1086. return;
  1087. }
  1088. wxLogMessage( wxT("Creating wxBitmapDataObject...") );
  1089. wxYield();
  1090. if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
  1091. {
  1092. wxLogError(wxT("Can't copy image to the clipboard."));
  1093. }
  1094. else
  1095. {
  1096. wxLogMessage(wxT("Image has been put on the clipboard.") );
  1097. wxLogMessage(wxT("You can paste it now and look at it.") );
  1098. }
  1099. wxTheClipboard->Close();
  1100. }
  1101. void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
  1102. {
  1103. if ( !wxTheClipboard->Open() )
  1104. {
  1105. wxLogError(wxT("Can't open clipboard."));
  1106. return;
  1107. }
  1108. if ( !wxTheClipboard->IsSupported(wxDF_BITMAP) )
  1109. {
  1110. wxLogWarning(wxT("No bitmap on clipboard"));
  1111. wxTheClipboard->Close();
  1112. return;
  1113. }
  1114. wxBitmapDataObject data;
  1115. if ( !wxTheClipboard->GetData(data) )
  1116. {
  1117. wxLogError(wxT("Can't paste bitmap from the clipboard"));
  1118. }
  1119. else
  1120. {
  1121. const wxBitmap& bmp = data.GetBitmap();
  1122. wxLogMessage(wxT("Bitmap %dx%d pasted from the clipboard"),
  1123. bmp.GetWidth(), bmp.GetHeight());
  1124. ShowBitmap(bmp);
  1125. }
  1126. wxTheClipboard->Close();
  1127. }
  1128. #if wxUSE_METAFILE
  1129. void DnDFrame::OnPasteMetafile(wxCommandEvent& WXUNUSED(event))
  1130. {
  1131. if ( !wxTheClipboard->Open() )
  1132. {
  1133. wxLogError(wxT("Can't open clipboard."));
  1134. return;
  1135. }
  1136. if ( !wxTheClipboard->IsSupported(wxDF_METAFILE) )
  1137. {
  1138. wxLogWarning(wxT("No metafile on clipboard"));
  1139. }
  1140. else
  1141. {
  1142. wxMetaFileDataObject data;
  1143. if ( !wxTheClipboard->GetData(data) )
  1144. {
  1145. wxLogError(wxT("Can't paste metafile from the clipboard"));
  1146. }
  1147. else
  1148. {
  1149. const wxMetaFile& mf = data.GetMetafile();
  1150. wxLogMessage(wxT("Metafile %dx%d pasted from the clipboard"),
  1151. mf.GetWidth(), mf.GetHeight());
  1152. ShowMetaFile(mf);
  1153. }
  1154. }
  1155. wxTheClipboard->Close();
  1156. }
  1157. #endif // wxUSE_METAFILE
  1158. // ----------------------------------------------------------------------------
  1159. // file clipboard
  1160. // ----------------------------------------------------------------------------
  1161. void DnDFrame::OnCopyFiles(wxCommandEvent& WXUNUSED(event))
  1162. {
  1163. #ifdef __WXMSW__
  1164. wxFileDialog dialog(this, wxT("Select a file to copy"), wxEmptyString, wxEmptyString,
  1165. wxT("All files (*.*)|*.*"), 0);
  1166. wxArrayString filenames;
  1167. while ( dialog.ShowModal() == wxID_OK )
  1168. {
  1169. filenames.Add(dialog.GetPath());
  1170. }
  1171. if ( !filenames.IsEmpty() )
  1172. {
  1173. wxFileDataObject *dobj = new wxFileDataObject;
  1174. size_t count = filenames.GetCount();
  1175. for ( size_t n = 0; n < count; n++ )
  1176. {
  1177. dobj->AddFile(filenames[n]);
  1178. }
  1179. wxClipboardLocker locker;
  1180. if ( !locker )
  1181. {
  1182. wxLogError(wxT("Can't open clipboard"));
  1183. }
  1184. else
  1185. {
  1186. if ( !wxTheClipboard->AddData(dobj) )
  1187. {
  1188. wxLogError(wxT("Can't copy file(s) to the clipboard"));
  1189. }
  1190. else
  1191. {
  1192. wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
  1193. count, count == 1 ? wxEmptyString : wxEmptyString);
  1194. }
  1195. }
  1196. }
  1197. else
  1198. {
  1199. wxLogStatus(this, wxT("Aborted"));
  1200. }
  1201. #else // !MSW
  1202. wxLogError(wxT("Sorry, not implemented"));
  1203. #endif // MSW/!MSW
  1204. }
  1205. void DnDFrame::OnCopyURL(wxCommandEvent& WXUNUSED(event))
  1206. {
  1207. // Just hard code it for now, we could ask the user but the point here is
  1208. // to test copying URLs, it doesn't really matter what it is.
  1209. const wxString url("http://www.wxwidgets.org/");
  1210. wxClipboardLocker locker;
  1211. if ( !!locker && wxTheClipboard->AddData(new wxURLDataObject(url)) )
  1212. {
  1213. wxLogStatus(this, "Copied URL \"%s\" to %s.",
  1214. url,
  1215. GetMenuBar()->IsChecked(Menu_UsePrimary)
  1216. ? "primary selection"
  1217. : "clipboard");
  1218. }
  1219. else
  1220. {
  1221. wxLogError("Failed to copy URL.");
  1222. }
  1223. }
  1224. // ---------------------------------------------------------------------------
  1225. // text clipboard
  1226. // ---------------------------------------------------------------------------
  1227. void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
  1228. {
  1229. if ( !wxTheClipboard->Open() )
  1230. {
  1231. wxLogError(wxT("Can't open clipboard."));
  1232. return;
  1233. }
  1234. if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
  1235. {
  1236. wxLogError(wxT("Can't copy data to the clipboard"));
  1237. }
  1238. else
  1239. {
  1240. wxLogMessage(wxT("Text '%s' put on the clipboard"), m_strText.c_str());
  1241. }
  1242. wxTheClipboard->Close();
  1243. }
  1244. void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
  1245. {
  1246. if ( !wxTheClipboard->Open() )
  1247. {
  1248. wxLogError(wxT("Can't open clipboard."));
  1249. return;
  1250. }
  1251. if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
  1252. {
  1253. wxLogWarning(wxT("No text data on clipboard"));
  1254. wxTheClipboard->Close();
  1255. return;
  1256. }
  1257. wxTextDataObject text;
  1258. if ( !wxTheClipboard->GetData(text) )
  1259. {
  1260. wxLogError(wxT("Can't paste data from the clipboard"));
  1261. }
  1262. else
  1263. {
  1264. wxLogMessage(wxT("Text '%s' pasted from the clipboard"),
  1265. text.GetText().c_str());
  1266. }
  1267. wxTheClipboard->Close();
  1268. }
  1269. #if wxUSE_DRAG_AND_DROP
  1270. // ----------------------------------------------------------------------------
  1271. // Notifications called by the base class
  1272. // ----------------------------------------------------------------------------
  1273. bool DnDText::OnDropText(wxCoord, wxCoord, const wxString& text)
  1274. {
  1275. m_pOwner->Append(text);
  1276. return true;
  1277. }
  1278. bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
  1279. {
  1280. size_t nFiles = filenames.GetCount();
  1281. wxString str;
  1282. str.Printf( wxT("%d files dropped"), (int)nFiles);
  1283. if (m_pOwner != NULL)
  1284. {
  1285. m_pOwner->Append(str);
  1286. for ( size_t n = 0; n < nFiles; n++ )
  1287. m_pOwner->Append(filenames[n]);
  1288. }
  1289. return true;
  1290. }
  1291. // ----------------------------------------------------------------------------
  1292. // DnDShapeDialog
  1293. // ----------------------------------------------------------------------------
  1294. DnDShapeDialog::DnDShapeDialog(wxFrame *parent, DnDShape *shape)
  1295. :wxDialog( parent, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
  1296. wxSize( 40, 40 ),
  1297. wxDEFAULT_DIALOG_STYLE | wxRAISED_BORDER | wxRESIZE_BORDER )
  1298. {
  1299. m_shape = shape;
  1300. wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
  1301. // radio box
  1302. wxBoxSizer* shapesSizer = new wxBoxSizer( wxHORIZONTAL );
  1303. const wxString choices[] = { wxT("None"), wxT("Triangle"),
  1304. wxT("Rectangle"), wxT("Ellipse") };
  1305. m_radio = new wxRadioBox( this, wxID_ANY, wxT("&Shape"),
  1306. wxDefaultPosition, wxDefaultSize, 4, choices, 4,
  1307. wxRA_SPECIFY_COLS );
  1308. shapesSizer->Add( m_radio, 0, wxGROW|wxALL, 5 );
  1309. topSizer->Add( shapesSizer, 0, wxALL, 2 );
  1310. // attributes
  1311. wxStaticBox* box = new wxStaticBox( this, wxID_ANY, wxT("&Attributes") );
  1312. wxStaticBoxSizer* attrSizer = new wxStaticBoxSizer( box, wxHORIZONTAL );
  1313. wxFlexGridSizer* xywhSizer = new wxFlexGridSizer( 2 );
  1314. wxStaticText* st;
  1315. st = new wxStaticText( this, wxID_ANY, wxT("Position &X:") );
  1316. m_textX = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
  1317. wxSize( 30, 20 ) );
  1318. xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
  1319. xywhSizer->Add( m_textX, 1, wxGROW|wxALL, 2 );
  1320. st = new wxStaticText( this, wxID_ANY, wxT("Size &width:") );
  1321. m_textW = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
  1322. wxSize( 30, 20 ) );
  1323. xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
  1324. xywhSizer->Add( m_textW, 1, wxGROW|wxALL, 2 );
  1325. st = new wxStaticText( this, wxID_ANY, wxT("&Y:") );
  1326. m_textY = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
  1327. wxSize( 30, 20 ) );
  1328. xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
  1329. xywhSizer->Add( m_textY, 1, wxGROW|wxALL, 2 );
  1330. st = new wxStaticText( this, wxID_ANY, wxT("&height:") );
  1331. m_textH = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
  1332. wxSize( 30, 20 ) );
  1333. xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
  1334. xywhSizer->Add( m_textH, 1, wxGROW|wxALL, 2 );
  1335. wxButton* col = new wxButton( this, Button_Colour, wxT("&Colour...") );
  1336. attrSizer->Add( xywhSizer, 1, wxGROW );
  1337. attrSizer->Add( col, 0, wxALL|wxALIGN_CENTRE_VERTICAL, 2 );
  1338. topSizer->Add( attrSizer, 0, wxGROW|wxALL, 5 );
  1339. // buttons
  1340. wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
  1341. wxButton* bt;
  1342. bt = new wxButton( this, wxID_OK, wxT("Ok") );
  1343. buttonSizer->Add( bt, 0, wxALL, 2 );
  1344. bt = new wxButton( this, wxID_CANCEL, wxT("Cancel") );
  1345. buttonSizer->Add( bt, 0, wxALL, 2 );
  1346. topSizer->Add( buttonSizer, 0, wxALL|wxALIGN_RIGHT, 2 );
  1347. SetSizerAndFit( topSizer );
  1348. }
  1349. DnDShape *DnDShapeDialog::GetShape() const
  1350. {
  1351. switch ( m_shapeKind )
  1352. {
  1353. default:
  1354. case DnDShape::None: return NULL;
  1355. case DnDShape::Triangle: return new DnDTriangularShape(m_pos, m_size, m_col);
  1356. case DnDShape::Rectangle: return new DnDRectangularShape(m_pos, m_size, m_col);
  1357. case DnDShape::Ellipse: return new DnDEllipticShape(m_pos, m_size, m_col);
  1358. }
  1359. }
  1360. bool DnDShapeDialog::TransferDataToWindow()
  1361. {
  1362. if ( m_shape )
  1363. {
  1364. m_radio->SetSelection(m_shape->GetKind());
  1365. m_pos = m_shape->GetPosition();
  1366. m_size = m_shape->GetSize();
  1367. m_col = m_shape->GetColour();
  1368. }
  1369. else
  1370. {
  1371. m_radio->SetSelection(DnDShape::None);
  1372. m_pos = wxPoint(1, 1);
  1373. m_size = wxSize(100, 100);
  1374. }
  1375. m_textX->SetValue(wxString() << m_pos.x);
  1376. m_textY->SetValue(wxString() << m_pos.y);
  1377. m_textW->SetValue(wxString() << m_size.x);
  1378. m_textH->SetValue(wxString() << m_size.y);
  1379. return true;
  1380. }
  1381. bool DnDShapeDialog::TransferDataFromWindow()
  1382. {
  1383. m_shapeKind = (DnDShape::Kind)m_radio->GetSelection();
  1384. m_pos.x = wxAtoi(m_textX->GetValue());
  1385. m_pos.y = wxAtoi(m_textY->GetValue());
  1386. m_size.x = wxAtoi(m_textW->GetValue());
  1387. m_size.y = wxAtoi(m_textH->GetValue());
  1388. if ( !m_pos.x || !m_pos.y || !m_size.x || !m_size.y )
  1389. {
  1390. wxMessageBox(wxT("All sizes and positions should be non null!"),
  1391. wxT("Invalid shape"), wxICON_HAND | wxOK, this);
  1392. return false;
  1393. }
  1394. return true;
  1395. }
  1396. void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
  1397. {
  1398. wxColourData data;
  1399. data.SetChooseFull(true);
  1400. for (int i = 0; i < 16; i++)
  1401. {
  1402. wxColour colour((unsigned char)(i*16), (unsigned char)(i*16), (unsigned char)(i*16));
  1403. data.SetCustomColour(i, colour);
  1404. }
  1405. wxColourDialog dialog(this, &data);
  1406. if ( dialog.ShowModal() == wxID_OK )
  1407. {
  1408. m_col = dialog.GetColourData().GetColour();
  1409. }
  1410. }
  1411. // ----------------------------------------------------------------------------
  1412. // DnDShapeFrame
  1413. // ----------------------------------------------------------------------------
  1414. DnDShapeFrame *DnDShapeFrame::ms_lastDropTarget = NULL;
  1415. DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
  1416. : wxFrame(parent, wxID_ANY, wxT("Shape Frame"))
  1417. {
  1418. #if wxUSE_STATUSBAR
  1419. CreateStatusBar();
  1420. #endif // wxUSE_STATUSBAR
  1421. wxMenu *menuShape = new wxMenu;
  1422. menuShape->Append(Menu_Shape_New, wxT("&New default shape\tCtrl-S"));
  1423. menuShape->Append(Menu_Shape_Edit, wxT("&Edit shape\tCtrl-E"));
  1424. menuShape->AppendSeparator();
  1425. menuShape->Append(Menu_Shape_Clear, wxT("&Clear shape\tCtrl-L"));
  1426. wxMenu *menuClipboard = new wxMenu;
  1427. menuClipboard->Append(Menu_ShapeClipboard_Copy, wxT("&Copy\tCtrl-C"));
  1428. menuClipboard->Append(Menu_ShapeClipboard_Paste, wxT("&Paste\tCtrl-V"));
  1429. wxMenuBar *menubar = new wxMenuBar;
  1430. menubar->Append(menuShape, wxT("&Shape"));
  1431. menubar->Append(menuClipboard, wxT("&Clipboard"));
  1432. SetMenuBar(menubar);
  1433. #if wxUSE_STATUSBAR
  1434. SetStatusText(wxT("Press Ctrl-S to create a new shape"));
  1435. #endif // wxUSE_STATUSBAR
  1436. SetDropTarget(new DnDShapeDropTarget(this));
  1437. m_shape = NULL;
  1438. SetBackgroundColour(*wxWHITE);
  1439. }
  1440. DnDShapeFrame::~DnDShapeFrame()
  1441. {
  1442. if (m_shape)
  1443. delete m_shape;
  1444. }
  1445. void DnDShapeFrame::SetShape(DnDShape *shape)
  1446. {
  1447. if (m_shape)
  1448. delete m_shape;
  1449. m_shape = shape;
  1450. Refresh();
  1451. }
  1452. // callbacks
  1453. void DnDShapeFrame::OnDrag(wxMouseEvent& event)
  1454. {
  1455. if ( !m_shape )
  1456. {
  1457. event.Skip();
  1458. return;
  1459. }
  1460. // start drag operation
  1461. DnDShapeDataObject shapeData(m_shape);
  1462. wxDropSource source(shapeData, this);
  1463. const wxChar *pc = NULL;
  1464. switch ( source.DoDragDrop(true) )
  1465. {
  1466. default:
  1467. case wxDragError:
  1468. wxLogError(wxT("An error occurred during drag and drop operation"));
  1469. break;
  1470. case wxDragNone:
  1471. #if wxUSE_STATUSBAR
  1472. SetStatusText(wxT("Nothing happened"));
  1473. #endif // wxUSE_STATUSBAR
  1474. break;
  1475. case wxDragCopy:
  1476. pc = wxT("copied");
  1477. break;
  1478. case wxDragMove:
  1479. pc = wxT("moved");
  1480. if ( ms_lastDropTarget != this )
  1481. {
  1482. // don't delete the shape if we dropped it on ourselves!
  1483. SetShape(NULL);
  1484. }
  1485. break;
  1486. case wxDragCancel:
  1487. #if wxUSE_STATUSBAR
  1488. SetStatusText(wxT("Drag and drop operation cancelled"));
  1489. #endif // wxUSE_STATUSBAR
  1490. break;
  1491. }
  1492. if ( pc )
  1493. {
  1494. #if wxUSE_STATUSBAR
  1495. SetStatusText(wxString(wxT("Shape successfully ")) + pc);
  1496. #endif // wxUSE_STATUSBAR
  1497. }
  1498. //else: status text already set
  1499. }
  1500. void DnDShapeFrame::OnDrop(wxCoord x, wxCoord y, DnDShape *shape)
  1501. {
  1502. ms_lastDropTarget = this;
  1503. wxPoint pt(x, y);
  1504. #if wxUSE_STATUSBAR
  1505. wxString s;
  1506. s.Printf(wxT("Shape dropped at (%d, %d)"), pt.x, pt.y);
  1507. SetStatusText(s);
  1508. #endif // wxUSE_STATUSBAR
  1509. shape->Move(pt);
  1510. SetShape(shape);
  1511. }
  1512. void DnDShapeFrame::OnEditShape(wxCommandEvent& WXUNUSED(event))
  1513. {
  1514. DnDShapeDialog dlg(this, m_shape);
  1515. if ( dlg.ShowModal() == wxID_OK )
  1516. {
  1517. SetShape(dlg.GetShape());
  1518. #if wxUSE_STATUSBAR
  1519. if ( m_shape )
  1520. {
  1521. SetStatusText(wxT("You can now drag the shape to another frame"));
  1522. }
  1523. #endif // wxUSE_STATUSBAR
  1524. }
  1525. }
  1526. void DnDShapeFrame::OnNewShape(wxCommandEvent& WXUNUSED(event))
  1527. {
  1528. SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED));
  1529. #if wxUSE_STATUSBAR
  1530. SetStatusText(wxT("You can now drag the shape to another frame"));
  1531. #endif // wxUSE_STATUSBAR
  1532. }
  1533. void DnDShapeFrame::OnClearShape(wxCommandEvent& WXUNUSED(event))
  1534. {
  1535. SetShape(NULL);
  1536. }
  1537. void DnDShapeFrame::OnCopyShape(wxCommandEvent& WXUNUSED(event))
  1538. {
  1539. if ( m_shape )
  1540. {
  1541. wxClipboardLocker clipLocker;
  1542. if ( !clipLocker )
  1543. {
  1544. wxLogError(wxT("Can't open the clipboard"));
  1545. return;
  1546. }
  1547. wxTheClipboard->AddData(new DnDShapeDataObject(m_shape));
  1548. }
  1549. }
  1550. void DnDShapeFrame::OnPasteShape(wxCommandEvent& WXUNUSED(event))
  1551. {
  1552. wxClipboardLocker clipLocker;
  1553. if ( !clipLocker )
  1554. {
  1555. wxLogError(wxT("Can't open the clipboard"));
  1556. return;
  1557. }
  1558. DnDShapeDataObject shapeDataObject(NULL);
  1559. if ( wxTheClipboard->GetData(shapeDataObject) )
  1560. {
  1561. SetShape(shapeDataObject.GetShape());
  1562. }
  1563. else
  1564. {
  1565. wxLogStatus(wxT("No shape on the clipboard"));
  1566. }
  1567. }
  1568. void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent& event)
  1569. {
  1570. event.Enable( m_shape != NULL );
  1571. }
  1572. void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent& event)
  1573. {
  1574. event.Enable( wxTheClipboard->IsSupported(wxDataFormat(shapeFormatId)) );
  1575. }
  1576. void DnDShapeFrame::OnPaint(wxPaintEvent& event)
  1577. {
  1578. if ( m_shape )
  1579. {
  1580. wxPaintDC dc(this);
  1581. m_shape->Draw(dc);
  1582. }
  1583. else
  1584. {
  1585. event.Skip();
  1586. }
  1587. }
  1588. // ----------------------------------------------------------------------------
  1589. // DnDShape
  1590. // ----------------------------------------------------------------------------
  1591. DnDShape *DnDShape::New(const void *buf)
  1592. {
  1593. const ShapeDump& dump = *(const ShapeDump *)buf;
  1594. switch ( dump.k )
  1595. {
  1596. case Triangle:
  1597. return new DnDTriangularShape(wxPoint(dump.x, dump.y),
  1598. wxSize(dump.w, dump.h),
  1599. wxColour(dump.r, dump.g, dump.b));
  1600. case Rectangle:
  1601. return new DnDRectangularShape(wxPoint(dump.x, dump.y),
  1602. wxSize(dump.w, dump.h),
  1603. wxColour(dump.r, dump.g, dump.b));
  1604. case Ellipse:
  1605. return new DnDEllipticShape(wxPoint(dump.x, dump.y),
  1606. wxSize(dump.w, dump.h),
  1607. wxColour(dump.r, dump.g, dump.b));
  1608. default:
  1609. wxFAIL_MSG(wxT("invalid shape!"));
  1610. return NULL;
  1611. }
  1612. }
  1613. // ----------------------------------------------------------------------------
  1614. // DnDShapeDataObject
  1615. // ----------------------------------------------------------------------------
  1616. #if wxUSE_METAFILE
  1617. void DnDShapeDataObject::CreateMetaFile() const
  1618. {
  1619. wxPoint pos = m_shape->GetPosition();
  1620. wxSize size = m_shape->GetSize();
  1621. wxMetaFileDC dcMF(wxEmptyString, pos.x + size.x, pos.y + size.y);
  1622. m_shape->Draw(dcMF);
  1623. wxMetafile *mf = dcMF.Close();
  1624. DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
  1625. self->m_dobjMetaFile.SetMetafile(*mf);
  1626. self->m_hasMetaFile = true;
  1627. delete mf;
  1628. }
  1629. #endif // wxUSE_METAFILE
  1630. void DnDShapeDataObject::CreateBitmap() const
  1631. {
  1632. wxPoint pos = m_shape->GetPosition();
  1633. wxSize size = m_shape->GetSize();
  1634. int x = pos.x + size.x,
  1635. y = pos.y + size.y;
  1636. wxBitmap bitmap(x, y);
  1637. wxMemoryDC dc;
  1638. dc.SelectObject(bitmap);
  1639. dc.SetBrush(*wxWHITE_BRUSH);
  1640. dc.Clear();
  1641. m_shape->Draw(dc);
  1642. dc.SelectObject(wxNullBitmap);
  1643. DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
  1644. self->m_dobjBitmap.SetBitmap(bitmap);
  1645. self->m_hasBitmap = true;
  1646. }
  1647. #endif // wxUSE_DRAG_AND_DROP
  1648. // ----------------------------------------------------------------------------
  1649. // global functions
  1650. // ----------------------------------------------------------------------------
  1651. static void ShowBitmap(const wxBitmap& bitmap)
  1652. {
  1653. wxFrame *frame = new wxFrame(NULL, wxID_ANY, wxT("Bitmap view"));
  1654. #if wxUSE_STATUSBAR
  1655. frame->CreateStatusBar();
  1656. #endif // wxUSE_STATUSBAR
  1657. DnDCanvasBitmap *canvas = new DnDCanvasBitmap(frame);
  1658. canvas->SetBitmap(bitmap);
  1659. int w = bitmap.GetWidth(),
  1660. h = bitmap.GetHeight();
  1661. #if wxUSE_STATUSBAR
  1662. frame->SetStatusText(wxString::Format(wxT("%dx%d"), w, h));
  1663. #endif // wxUSE_STATUSBAR
  1664. frame->SetClientSize(w > 100 ? 100 : w, h > 100 ? 100 : h);
  1665. frame->Show(true);
  1666. }
  1667. #if wxUSE_METAFILE
  1668. static void ShowMetaFile(const wxMetaFile& metafile)
  1669. {
  1670. wxFrame *frame = new wxFrame(NULL, wxID_ANY, wxT("Metafile view"));
  1671. frame->CreateStatusBar();
  1672. DnDCanvasMetafile *canvas = new DnDCanvasMetafile(frame);
  1673. canvas->SetMetafile(metafile);
  1674. wxSize size = metafile.GetSize();
  1675. frame->SetStatusText(wxString::Format(wxT("%dx%d"), size.x, size.y));
  1676. frame->SetClientSize(size.x > 100 ? 100 : size.x,
  1677. size.y > 100 ? 100 : size.y);
  1678. frame->Show();
  1679. }
  1680. #endif // wxUSE_METAFILE
  1681. #endif // wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD