@@ -58,6 +58,8 @@ REHex::ToolDock::ToolDock(wxWindow *parent):
5858 m_bottom_notebook = new ToolNotebook (this , wxID_ANY, wxNB_BOTTOM);
5959 m_bottom_notebook->Bind (wxEVT_LEFT_DOWN, &REHex::ToolDock::OnNotebookLeftDown, this );
6060 m_bottom_notebook->Hide ();
61+
62+ m_dock_shadow = new DockShadow (this , wxRect (0 , 0 , 0 , 0 ));
6163}
6264
6365void REHex::ToolDock::AddMainPanel (wxWindow *main_panel)
@@ -545,6 +547,37 @@ REHex::ToolPanel *REHex::ToolDock::FindToolByName(const std::string &name) const
545547 return tool;
546548}
547549
550+ REHex::ToolDock::ToolNotebook *REHex::ToolDock::FindDockNotebook (const wxPoint &point, ToolNotebook *current_notebook)
551+ {
552+ ToolNotebook *dest_notebook = (ToolNotebook*)(FindChildByPoint (point));
553+ if (dest_notebook == NULL || dest_notebook != current_notebook)
554+ {
555+ wxPoint screen_point = ClientToScreen (point);
556+
557+ if (m_left_dock_site != NULL && m_left_dock_site->GetScreenRect ().Contains (screen_point))
558+ {
559+ dest_notebook = m_left_notebook;
560+ }
561+ else if (m_right_dock_site != NULL && m_right_dock_site->GetScreenRect ().Contains (screen_point))
562+ {
563+ dest_notebook = m_right_notebook;
564+ }
565+ else if (m_top_dock_site != NULL && m_top_dock_site->GetScreenRect ().Contains (screen_point))
566+ {
567+ dest_notebook = m_top_notebook;
568+ }
569+ else if (m_bottom_dock_site != NULL && m_bottom_dock_site->GetScreenRect ().Contains (screen_point))
570+ {
571+ dest_notebook = m_bottom_notebook;
572+ }
573+ else {
574+ dest_notebook = NULL ;
575+ }
576+ }
577+
578+ return dest_notebook;
579+ }
580+
548581void REHex::ToolDock::OnNotebookLeftDown (wxMouseEvent &event)
549582{
550583 ToolNotebook *notebook = (ToolNotebook*)(event.GetEventObject ());
@@ -580,6 +613,48 @@ void REHex::ToolDock::OnNotebookLeftDown(wxMouseEvent &event)
580613
581614void REHex::ToolDock::OnLeftUp (wxMouseEvent &event)
582615{
616+ if (m_drag_active)
617+ {
618+ ToolFrame *frame = FindFrameByTool (m_left_down_tool);
619+ ToolNotebook *notebook = FindNotebookByTool (m_left_down_tool);
620+
621+ assert (frame == NULL || notebook == NULL );
622+
623+ ToolNotebook *dest_notebook = FindDockNotebook (event.GetPosition (), notebook);
624+
625+ if (dest_notebook != NULL && dest_notebook != notebook)
626+ {
627+ if (notebook != NULL )
628+ {
629+ notebook->RemovePage (notebook->FindPage (m_left_down_tool));
630+
631+ if (notebook->GetPageCount () == 0 )
632+ {
633+ notebook->Hide ();
634+ }
635+ }
636+
637+ if (frame != NULL )
638+ {
639+ frame->GetSizer ()->Detach (m_left_down_tool);
640+ }
641+
642+ m_left_down_tool->Reparent (dest_notebook);
643+ dest_notebook->AddPage (m_left_down_tool, m_left_down_tool->label (), true );
644+
645+ if (dest_notebook->GetPageCount () == 1 )
646+ {
647+ ResetNotebookSize (dest_notebook);
648+ }
649+
650+ if (frame != NULL )
651+ {
652+ frame->Destroy ();
653+ m_tool_frames.erase (m_left_down_tool);
654+ }
655+ }
656+ }
657+
583658 if (m_drag_pending || m_drag_active)
584659 {
585660 ReleaseMouse ();
@@ -588,6 +663,7 @@ void REHex::ToolDock::OnLeftUp(wxMouseEvent &event)
588663 m_drag_active = false ;
589664
590665 DestroyDockSites ();
666+ m_dock_shadow->Hide ();
591667 }
592668
593669 event.Skip ();
@@ -601,6 +677,7 @@ void REHex::ToolDock::OnMouseCaptureLost(wxMouseCaptureLostEvent &event)
601677 m_drag_active = false ;
602678
603679 DestroyDockSites ();
680+ m_dock_shadow->Hide ();
604681 }
605682 else {
606683 event.Skip ();
@@ -631,67 +708,66 @@ void REHex::ToolDock::OnMotion(wxMouseEvent &event)
631708
632709 assert (frame == NULL || notebook == NULL );
633710
634- ToolNotebook *dest_notebook = (ToolNotebook*)(FindChildByPoint (event.GetPosition ()));
635- if (dest_notebook == NULL || dest_notebook != notebook)
636- {
637- wxPoint screen_mouse_point = ClientToScreen (event.GetPosition ());
638-
639- if (m_left_dock_site != NULL && m_left_dock_site->GetScreenRect ().Contains (screen_mouse_point))
640- {
641- dest_notebook = m_left_notebook;
642- }
643- else if (m_right_dock_site != NULL && m_right_dock_site->GetScreenRect ().Contains (screen_mouse_point))
644- {
645- dest_notebook = m_right_notebook;
646- }
647- else if (m_top_dock_site != NULL && m_top_dock_site->GetScreenRect ().Contains (screen_mouse_point))
648- {
649- dest_notebook = m_top_notebook;
650- }
651- else if (m_bottom_dock_site != NULL && m_bottom_dock_site->GetScreenRect ().Contains (screen_mouse_point))
652- {
653- dest_notebook = m_bottom_notebook;
654- }
655- else {
656- dest_notebook = NULL ;
657- }
658- }
711+ ToolNotebook *dest_notebook = FindDockNotebook (event.GetPosition (), notebook);
659712
660713 if (dest_notebook != NULL )
661714 {
662715 if (dest_notebook != notebook)
663716 {
664- if (notebook != NULL )
717+ if (dest_notebook-> IsShown () )
665718 {
666- notebook->RemovePage (notebook->FindPage (m_left_down_tool));
719+ m_dock_shadow->Move (dest_notebook->GetScreenRect ());
720+ m_dock_shadow->Show ();
721+ }
722+ else {
723+ wxPoint client_base = ClientToScreen (wxPoint (0 , 0 ));
724+ wxSize client_size = GetClientSize ();
725+
726+ wxSize min_size = m_left_down_tool->GetEffectiveMinSize ();
727+ wxSize best_size = m_left_down_tool->GetBestSize ();
728+
729+ wxRect rect;
667730
668- if (notebook->GetPageCount () == 0 )
731+ if (dest_notebook == m_top_notebook || dest_notebook == m_bottom_notebook)
732+ {
733+ rect.width = client_size.GetWidth ();
734+ rect.height = std::max (min_size.GetHeight (), best_size.GetHeight ());
735+ }
736+ else {
737+ rect.width = std::max (min_size.GetWidth (), best_size.GetWidth ());
738+ rect.height = client_size.GetHeight ();
739+ }
740+
741+ if (dest_notebook == m_left_notebook || dest_notebook == m_top_notebook)
742+ {
743+ rect.x = client_base.x ;
744+ rect.y = client_base.y ;
745+ }
746+ else if (dest_notebook == m_right_notebook)
747+ {
748+ rect.x = client_base.x + client_size.GetWidth () - rect.width ;
749+ rect.y = client_base.y ;
750+ }
751+ else if (dest_notebook == m_bottom_notebook)
669752 {
670- notebook->Hide ();
753+ rect.x = client_base.x ;
754+ rect.y = client_base.y + client_size.GetHeight () - rect.height ;
671755 }
756+
757+ m_dock_shadow->Move (rect);
758+ m_dock_shadow->Show ();
672759 }
673760
674- if (frame != NULL )
675- {
676- frame->GetSizer ()->Detach (m_left_down_tool);
677- }
678-
679- m_left_down_tool->Reparent (dest_notebook);
680- dest_notebook->AddPage (m_left_down_tool, m_left_down_tool->label (), true );
681-
682- if (dest_notebook->GetPageCount () == 1 )
683- {
684- ResetNotebookSize (dest_notebook);
685- }
686-
687- if (frame != NULL )
688- {
689- frame->Destroy ();
690- m_tool_frames.erase (m_left_down_tool);
691- }
761+ /* On Windows, the transparent wxPopupWindow isn't redrawn when the frame moves
762+ * around under it and I can't figure out a way to trigger an update that doesn't
763+ * result in the popup drawing over itself until its effectively opaque, so we just
764+ * hide the frame when the cursor is over a dock site on Windows.
765+ */
766+ #ifdef _WIN32
767+ assert (frame != NULL );
768+ frame->Hide ();
769+ #endif
692770 }
693-
694- DestroyDockSites ();
695771 }
696772 else {
697773 if (notebook != NULL )
@@ -706,21 +782,26 @@ void REHex::ToolDock::OnMotion(wxMouseEvent &event)
706782
707783 wxPoint frame_pos = ClientToScreen (event.GetPosition ());
708784
709- if (frame ! = NULL )
785+ if (frame = = NULL )
710786 {
711- frame->SetPosition (frame_pos);
712- }
713- else {
714787 frame = new ToolFrame (this , wxDefaultPosition, wxDefaultSize, m_left_down_tool);
715788 frame->SetPosition (frame_pos);
716- frame->Show ();
717789
718790 frame->Bind (wxEVT_CLOSE_WINDOW, &REHex::ToolDock::OnFrameClose, this );
719791
720792 m_tool_frames.emplace (m_left_down_tool, frame);
721793 }
722794
723795 SetupDockSites ();
796+ m_dock_shadow->Hide ();
797+
798+ frame->Show ();
799+ }
800+
801+ if (frame != NULL )
802+ {
803+ wxPoint frame_pos = ClientToScreen (event.GetPosition ());
804+ frame->SetPosition (frame_pos);
724805 }
725806 }
726807
@@ -1013,3 +1094,49 @@ REHex::ToolDock::DockSite::DockSite(wxWindow *parent, const wxBitmap &image, Anc
10131094
10141095 SetPosition (wxPoint (x, y));
10151096}
1097+
1098+ BEGIN_EVENT_TABLE (REHex::ToolDock::DockShadow, wxPopupWindow)
1099+ EVT_PAINT(REHex::ToolDock::DockShadow::OnPaint)
1100+ END_EVENT_TABLE()
1101+
1102+ REHex::ToolDock::DockShadow::DockShadow(wxWindow *parent, const wxRect &rect):
1103+ wxPopupWindow()
1104+ {
1105+ SetBackgroundStyle (wxBG_STYLE_TRANSPARENT);
1106+ Create (parent);
1107+
1108+ Move (rect);
1109+ }
1110+
1111+ void REHex::ToolDock::DockShadow::Move (const wxRect &rect)
1112+ {
1113+ /* In wxGTK (at least), changing the wxPopupWindow size/position to one which overlaps
1114+ * with the previous position causes some weird bug where the client/paint area only covers
1115+ * the intersection between the new/old positions, returning the size/position to the
1116+ * previous position restores correct behaviour until you try moving it to overlap again.
1117+ *
1118+ * So we set the position miles off screen and *then* put it where we need it instead.
1119+ */
1120+ #ifdef __WXGTK__
1121+ SetPosition (wxPoint (999999 , 999999 ));
1122+ #endif
1123+
1124+ SetPosition (wxPoint (rect.x , rect.y ));
1125+ SetSize (wxSize (rect.width , rect.height ));
1126+ }
1127+
1128+ void REHex::ToolDock::DockShadow::OnPaint (wxPaintEvent &event)
1129+ {
1130+ wxPaintDC dc (this );
1131+
1132+ wxGraphicsContext *gc = wxGraphicsContext::Create (dc);
1133+ if (gc)
1134+ {
1135+ wxSize client_size = GetClientSize ();
1136+
1137+ gc->SetBrush (wxBrush (wxColour (0xF6 , 0xD3 , 0x2D , 100 )));
1138+ gc->DrawRectangle (0 , 0 , client_size.GetWidth (), client_size.GetHeight ());
1139+
1140+ delete gc;
1141+ }
1142+ }
0 commit comments