Implement dc mirroring for RTL.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41156 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2006-09-11 10:32:43 +00:00
parent bdb427d70e
commit 847dfdb422
6 changed files with 126 additions and 50 deletions

View File

@@ -72,6 +72,7 @@ protected:
virtual void DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ); virtual void DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height );
virtual void DoSetClippingRegionAsRegion( const wxRegion &region ); virtual void DoSetClippingRegionAsRegion( const wxRegion &region );
public: public:
virtual wxCoord GetCharWidth() const; virtual wxCoord GetCharWidth() const;
virtual wxCoord GetCharHeight() const; virtual wxCoord GetCharHeight() const;
@@ -94,6 +95,10 @@ public:
virtual wxSize GetPPI() const; virtual wxSize GetPPI() const;
virtual int GetDepth() const; virtual int GetDepth() const;
// overrriden here for RTL
virtual void SetDeviceOrigin( wxCoord x, wxCoord y );
virtual void SetAxisOrientation( bool xLeftRight, bool yBottomUp );
// protected: // protected:
// implementation // implementation
// -------------- // --------------

View File

@@ -119,6 +119,9 @@ public:
wxCoord width, wxCoord width,
wxCoord widthTotal) const; wxCoord widthTotal) const;
virtual bool IsExposed( int x, int y ) const;
virtual bool IsExposed( int x, int y, int w, int h ) const;
// currently wxGTK2-only // currently wxGTK2-only
void SetDoubleBuffered(bool on); void SetDoubleBuffered(bool on);

View File

@@ -2242,7 +2242,12 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
if ( image != NO_IMAGE ) if ( image != NO_IMAGE )
{ {
dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, total_h ); #ifdef __WXGTK__
if (GetLayoutDirection() == wxLayout_RightToLeft)
dc.SetClippingRegion( item->GetX()+image_w-2, item->GetY(), image_w-2, total_h );
else
#endif
dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, total_h );
m_imageListNormal->Draw( image, dc, m_imageListNormal->Draw( image, dc,
item->GetX(), item->GetX(),
item->GetY() +((total_h > image_h)?((total_h-image_h)/2):0), item->GetY() +((total_h > image_h)?((total_h-image_h)/2):0),

View File

@@ -323,6 +323,15 @@ wxWindowDC::wxWindowDC( wxWindow *window )
standard (as e.g. wxStatusBar) */ standard (as e.g. wxStatusBar) */
m_owner = window; m_owner = window;
if (m_owner && m_owner->m_wxwindow && (m_owner->GetLayoutDirection() == wxLayout_RightToLeft))
{
m_signX = -1;
gint width;
gdk_window_get_geometry( GTK_PIZZA(m_owner->m_wxwindow)->bin_window,
NULL, NULL, &width, NULL, NULL );
m_deviceOriginX = width;;
}
} }
wxWindowDC::~wxWindowDC() wxWindowDC::~wxWindowDC()
@@ -1039,7 +1048,10 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
int w = bitmap.GetWidth(); int w = bitmap.GetWidth();
int h = bitmap.GetHeight(); int h = bitmap.GetHeight();
if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft)
xx -= w;
CalcBoundingBox( x, y ); CalcBoundingBox( x, y );
CalcBoundingBox( x + w, y + h ); CalcBoundingBox( x + w, y + h );
@@ -1451,7 +1463,10 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
} }
// Draw layout. // Draw layout.
gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft)
gdk_draw_layout( m_window, m_textGC, x-w, y, m_layout );
else
gdk_draw_layout( m_window, m_textGC, x, y, m_layout );
// reset unscaled size // reset unscaled size
pango_font_description_set_size( m_fontdesc, oldSize ); pango_font_description_set_size( m_fontdesc, oldSize );
@@ -1468,8 +1483,12 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h);
gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor());
} }
// Draw layout. // Draw layout.
gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft)
gdk_draw_layout( m_window, m_textGC, x-w, y, m_layout );
else
gdk_draw_layout( m_window, m_textGC, x, y, m_layout );
} }
if (underlined) if (underlined)
@@ -2197,6 +2216,25 @@ void wxWindowDC::Destroy()
m_bgGC = (GdkGC*) NULL; m_bgGC = (GdkGC*) NULL;
} }
void wxWindowDC::SetDeviceOrigin( wxCoord x, wxCoord y )
{
m_deviceOriginX = x;
m_deviceOriginY = y;
ComputeScaleAndOrigin();
}
void wxWindowDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
{
m_signX = (xLeftRight ? 1 : -1);
m_signY = (yBottomUp ? -1 : 1);
if (m_owner && m_owner->m_wxwindow && (m_owner->GetLayoutDirection() == wxLayout_RightToLeft))
m_signX = -m_signX;
ComputeScaleAndOrigin();
}
void wxWindowDC::ComputeScaleAndOrigin() void wxWindowDC::ComputeScaleAndOrigin()
{ {
const wxRealPoint origScale(m_scaleX, m_scaleY); const wxRealPoint origScale(m_scaleX, m_scaleY);

View File

@@ -35,11 +35,6 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "wx/gtk/win_gtk.h" #include "wx/gtk/win_gtk.h"
// RR: After a correction to the orientation of the sash
// this doesn't seem to be required anymore and it
// seems to confuse some themes so USE_ERASE_RECT=0
#define USE_ERASE_RECT 0
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxRendererGTK: our wxRendererNative implementation // wxRendererGTK: our wxRendererNative implementation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -296,9 +291,6 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win,
const bool isVert = orient == wxVERTICAL; const bool isVert = orient == wxVERTICAL;
GdkRectangle rect; GdkRectangle rect;
#if USE_ERASE_RECT
GdkRectangle erase_rect;
#endif
if ( isVert ) if ( isVert )
{ {
@@ -308,13 +300,6 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win,
rect.y = 0; rect.y = 0;
rect.width = full_size; rect.width = full_size;
rect.height = h; rect.height = h;
#if USE_ERASE_RECT
erase_rect.x = position;
erase_rect.y = 0;
erase_rect.width = full_size;
erase_rect.height = h;
#endif
} }
else // horz else // horz
{ {
@@ -324,33 +309,11 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win,
rect.y = position; rect.y = position;
rect.height = full_size; rect.height = full_size;
rect.width = w; rect.width = w;
#if USE_ERASE_RECT
erase_rect.y = position;
erase_rect.x = 0;
erase_rect.height = full_size;
erase_rect.width = w;
#endif
} }
#if USE_ERASE_RECT int x_diff = 0;
// we must erase everything first, otherwise the garbage if (win->GetLayoutDirection() == wxLayout_RightToLeft)
// from the old sash is left when dragging it x_diff = rect.width;
gtk_paint_flat_box
(
win->m_wxwindow->style,
GTK_PIZZA(win->m_wxwindow)->bin_window,
GTK_STATE_NORMAL,
GTK_SHADOW_NONE,
NULL,
win->m_wxwindow,
(char *)"viewportbin", // const_cast
erase_rect.x,
erase_rect.y,
erase_rect.width,
erase_rect.height
);
#endif
gtk_paint_handle gtk_paint_handle
( (
@@ -361,8 +324,8 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win,
NULL /* no clipping */, NULL /* no clipping */,
win->m_wxwindow, win->m_wxwindow,
"paned", "paned",
rect.x, dc.LogicalToDeviceX(rect.x) - x_diff,
rect.y, dc.LogicalToDeviceY(rect.y),
rect.width, rect.width,
rect.height, rect.height,
isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL

View File

@@ -486,6 +486,7 @@ gtk_window_expose_callback( GtkWidget *widget,
GtkPizza *pizza = GTK_PIZZA( widget ); GtkPizza *pizza = GTK_PIZZA( widget );
if (gdk_event->window != pizza->bin_window) return FALSE; if (gdk_event->window != pizza->bin_window) return FALSE;
#if 0 #if 0
if (win->GetName()) if (win->GetName())
{ {
@@ -515,7 +516,6 @@ gtk_window_expose_callback( GtkWidget *widget,
win->GtkSendPaintEvents(); win->GtkSendPaintEvents();
// Let parent window draw window-less widgets // Let parent window draw window-less widgets
(* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
@@ -1282,6 +1282,9 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
wxPoint pt = win->GetClientAreaOrigin(); wxPoint pt = win->GetClientAreaOrigin();
event.m_x = (wxCoord)gdk_event->x - pt.x; event.m_x = (wxCoord)gdk_event->x - pt.x;
event.m_y = (wxCoord)gdk_event->y - pt.y; event.m_y = (wxCoord)gdk_event->y - pt.y;
if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft))
event.m_x = GTK_PIZZA(win->m_wxwindow)->m_width - event.m_x;
event.SetEventObject( win ); event.SetEventObject( win );
event.SetId( win->GetId() ); event.SetId( win->GetId() );
@@ -2127,6 +2130,17 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight)) if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
return; return;
#if 0
wxPrintf( wxT("size_allocate ") );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
wxPrintf( win->GetClassInfo()->GetClassName() );
wxPrintf( wxT(" %d %d %d %d\n"),
alloc->x,
alloc->y,
alloc->width,
alloc->height );
#endif
GTK_PIZZA(win->m_wxwindow)->m_width = alloc->width; GTK_PIZZA(win->m_wxwindow)->m_width = alloc->width;
win->m_oldClientWidth = client_width; win->m_oldClientWidth = client_width;
@@ -2595,7 +2609,8 @@ void wxWindowGTK::PostCreation()
g_signal_connect (m_wxwindow, "expose_event", g_signal_connect (m_wxwindow, "expose_event",
G_CALLBACK (gtk_window_expose_callback), this); G_CALLBACK (gtk_window_expose_callback), this);
gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); if (GetLayoutDirection() == wxLayout_LeftToRight)
gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
} }
// Create input method handler // Create input method handler
@@ -3727,6 +3742,8 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
{ {
p = NULL; p = NULL;
} }
p = NULL;
gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE ); gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
} }
@@ -3761,6 +3778,20 @@ void wxWindowGTK::GtkUpdate()
} }
} }
bool wxWindowGTK::IsExposed( int x, int y ) const
{
return m_updateRegion.Contains(x, y) != wxOutRegion;
}
bool wxWindowGTK::IsExposed( int x, int y, int w, int h ) const
{
if (GetLayoutDirection() == wxLayout_RightToLeft)
return m_updateRegion.Contains(x-w, y, w, h) != wxOutRegion;
else
return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
}
void wxWindowGTK::GtkSendPaintEvents() void wxWindowGTK::GtkSendPaintEvents()
{ {
if (!m_wxwindow) if (!m_wxwindow)
@@ -3772,6 +3803,34 @@ void wxWindowGTK::GtkSendPaintEvents()
// Clip to paint region in wxClientDC // Clip to paint region in wxClientDC
m_clipPaintRegion = true; m_clipPaintRegion = true;
wxRegion maybe_rtl_region = m_updateRegion;
#if 0
if (GetLayoutDirection() == wxLayout_RightToLeft)
{
maybe_rtl_region.Clear();
gint width;
gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window,
NULL, NULL, &width, NULL, NULL );
wxRegionIterator upd( m_updateRegion );
while (upd)
{
wxRect rect;
rect.x = upd.GetX();
rect.y = upd.GetY();
rect.width = upd.GetWidth();
rect.height = upd.GetHeight();
rect.x = width - rect.x - rect.width;
maybe_rtl_region.Union( rect );
++upd;
}
}
#endif
// widget to draw on // widget to draw on
GtkPizza *pizza = GTK_PIZZA (m_wxwindow); GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
@@ -3807,8 +3866,9 @@ void wxWindowGTK::GtkSendPaintEvents()
} }
} }
else else
{ {
m_updateRegion = maybe_rtl_region;
wxWindowDC dc( (wxWindow*)this ); wxWindowDC dc( (wxWindow*)this );
dc.SetClippingRegion( m_updateRegion ); dc.SetClippingRegion( m_updateRegion );
@@ -3818,6 +3878,8 @@ void wxWindowGTK::GtkSendPaintEvents()
GetEventHandler()->ProcessEvent(erase_event); GetEventHandler()->ProcessEvent(erase_event);
} }
m_updateRegion = maybe_rtl_region;
wxNcPaintEvent nc_paint_event( GetId() ); wxNcPaintEvent nc_paint_event( GetId() );
nc_paint_event.SetEventObject( this ); nc_paint_event.SetEventObject( this );
GetEventHandler()->ProcessEvent( nc_paint_event ); GetEventHandler()->ProcessEvent( nc_paint_event );