Exemple #1
0
void wxPlotDrawerXAxis::Draw(wxDC *dc, bool refresh)
{
    wxCHECK_RET(dc, wxT("Invalid dc"));

    wxRect dcRect(GetDCRect());

    // Draw background
    if (refresh)
    {
        dc->SetBrush(m_backgroundBrush.GetBrush());
        dc->SetPen(*wxTRANSPARENT_PEN);
        dc->DrawRectangle(dcRect);
    }

    wxFont tickFont = m_tickFont;
    if (m_font_scale != 1)
        tickFont.SetPointSize( wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale)) );

    dc->SetTextForeground( m_tickColour.GetColour() );
    dc->SetFont( tickFont );

    wxString label;

    // center the text in the window
    int x, y;
    dc->GetTextExtent(wxT("5"), &x, &y);
    int y_pos = (GetDCRect().height - y)/2 + 2; // FIXME I want to center this
    // double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step;
    int i, count = m_tickPositions.GetCount();
    for (i=0; i<count; i++)
    {
        dc->DrawText(m_tickLabels[i], m_tickPositions[i], y_pos);

//        if (!IsFinite(current, wxT("axis label is not finite")))
//            break;
//        label.Printf( m_xAxisTickFormat.c_str(), current );
//        dc->DrawText(label, m_xAxisTicks[i], y_pos);
//        current += m_xAxisTick_step;
    }

#ifdef DRAW_BORDERS
    // Test code for sizing to show the extent of the axes
    dc->SetBrush( *wxTRANSPARENT_BRUSH );
    dc->SetPen( *wxRED_PEN );
    dc->DrawRectangle(wxRect(wxPoint(0,0), clientSize));
#endif // DRAW_BORDERS
}
Exemple #2
0
// HRGN CScreenCapture::GetChangesRgn()
// {
// 	
// 	// get changes
// 	CChangeRecorder::CHANGES changes;
// 	if(!m_recoder.GetChangeList(changes))
// 	{
// 		DebugOutF(filelog::log_error,"GetChangeList failed");
// 		return 0;
// 	}
// 	HRGN hrgn = CreateRectRgn(0,0,0,0);
// 	if (hrgn == 0)
// 	{
// 		DebugOutF(filelog::log_error,"CreateRectRgn failed with %d",GetLastError() );
// 		return 0;
// 	}
// 	HRGN hTemp = CreateRectRgn(0,0,0,0);
// 	if (hTemp == 0)
// 	{
// 		DebugOutF(filelog::log_error,"CreateRectRgn failed with %d",GetLastError() );
// 		DeleteObject(hrgn);
// 		return 0;
// 	}
// 	RECT maxrc =  GetDCRect(m_hDev);
// 
// 	for(CChangeRecorder::CHANGES::iterator it =changes.begin();
// 		it != changes.end();
// 		it++)
// 	{
// 		RECT rc = {0} ;
// 		IntersectRect(&rc,&*it,&maxrc);
// 		SetRectRgn(hTemp,rc.left,rc.top,rc.right,rc.bottom);
// 		CombineRgn(hrgn,hrgn,hTemp,RGN_OR);
// 	}
// 	RECT box;
// 	GetRgnBox(hrgn,&box);
// 	//DebugOutF(filelog::log_error,"%d,%d,%d,%d",box.left,box,box.right,box.bottom);
// 	DeleteObject(hTemp);
// 	return hrgn;
// }
HRESULT CScreenCapture::Capture(const RECT&rc,IScreenBufferStream**ppStream)
{
	TrackDebugOut;
	CAutoLock<CCrtSection>	lock(m_csLock);
	if (NeedToReset())
	{
		TrackDebugOut;
		if(!Reset())
		{
			DebugOutF(filelog::log_error,"CScreenCapture::Reset failed");
			return E_FAIL;
		}
	}
	{
		TrackDebugOut;
	}

 	CRefObj<CScreenBuffer> pBuf = new CScreenBuffer();
 	if(!pBuf->Create(m_hDev,rc))
 	{
 		DebugOutF(filelog::log_error,"CScreenCapture::Capture failed");
		Reset();
 		return E_FAIL ;
 	}
	
	RECT rcscreen =GetDCRect(m_hDev);
	RECT rcdest={0};
	IntersectRect(&rcdest,&rcscreen,&rc);

	// capture DirectDraw overlay image
	AppendDDrawOverlay(pBuf->GetDC(),&rcdest);

	CComObject<CScreenBufferStream>* pScreen;
	HRESULT hr = CComObject<CScreenBufferStream>::CreateInstance(&pScreen);
	if(	FAILED(hr)	)
	{
		DebugOutF(filelog::log_error,"CreateInstance CScreenBufferStream failed with 0x%x",hr);
		return hr ;
	}
	pScreen->AddRef();
	pScreen->SetBuffer(pBuf);

	DebugOutF(filelog::log_info,("capture screen (%d,%d,%d,%d) ok"),rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top);
	*ppStream = pScreen;
	return S_OK;
}
Exemple #3
0
bool CScreenBuffer::Create(HDC hDev,const RECT & rc,LPCTSTR szName )
{
	TrackDebugOut;
	Destroy();
	m_hMemDC = CreateCompatibleDC(hDev);
	if(m_hMemDC == NULL){
		DebugOutF(filelog::log_error,("CreateCompatibleDC failed with %d"),GetLastError() );
		return false;
	}
	RECT rcscreen = GetDCRect(hDev);
	RECT rcdest;
	IntersectRect(&rcdest,&rcscreen,&rc);

	LONG lWidth		= rcdest.right - rcdest.left;
	LONG lHeight	= rcdest.bottom - rcdest.top; 
	LONG lBitsPPix	= 32;//GetDeviceCaps(hDev,BITSPIXEL);
	LONG dwImageSize = lHeight*CalculatePitch(CalculateLine(lWidth,lBitsPPix));


	// save [bmp file header] + [bmp info header] + [bmp data] to the file mapping object
	//DWORD filesize = 0;
	LONG biClrUsed = 0;
	RGBQUAD rgbquad[256];
	if (lBitsPPix < 16)
	{
		TrackDebugOut;
		biClrUsed = GetDIBColorTable(hDev,0,256,rgbquad);
	}
	
	if(!CFileMappingBitmap::Create(lWidth,lHeight,lBitsPPix,biClrUsed,rgbquad,szName))
	{
		return false;
	}
	
	m_hBmp = CreateDIBSection(m_hMemDC,(BITMAPINFO*)InfoHeader(),DIB_RGB_COLORS, (void**)&m_pBuff, GetHandle(), FileHeader()->bfOffBits);
	if(m_hBmp == NULL){
		DebugOutF(filelog::log_error,("CreateDIBSection failed %d"),GetLastError() );
		return false;
	}
	SelectObject(m_hMemDC,m_hBmp);
	//HDC hdc = GetDC(0);
	BitBlt(m_hMemDC,0,0,rcdest.right-rcdest.left,rcdest.bottom-rcdest.top,hDev,rcdest.left,rcdest.top,SRCCOPY|CAPTUREBLT);
	//ReleaseDC(0,hdc);
	return true;
}
Exemple #4
0
void wxPlotDrawerMarker::Draw(wxDC *dc, const wxArrayPlotMarker& markers)
{
    wxCHECK_RET(dc && m_owner, wxT("dc or owner"));
    INITIALIZE_FAST_GRAPHICS

    wxRect dcRect(GetDCRect());
    wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect );

    double x0 = 0, y0 = 0, x1 = 0, y1 = 0;
    int n, count = markers.GetCount();
    for (n = 0; n < count; n++)
    {
        const wxPlotMarker &marker = markers[n];
        wxCHECK_RET(marker.Ok(), wxT("Invalid marker"));
        wxRect2DDouble r = marker.GetPlotRect();
        x0 = r.m_x;
        y0 = r.m_y;
        x1 = r.GetRight();
        y1 = r.GetBottom();

        if (marker.GetPen().Ok())
            dc->SetPen(marker.GetPen().GetPen());
        if (marker.GetBrush().Ok())
            dc->SetBrush(marker.GetBrush().GetBrush());

        // determine what to draw
        int marker_type = marker.GetMarkerType();
        wxSize size     = marker.GetSize();

        if (marker_type == wxPLOTMARKER_BITMAP)
        {
            wxBitmap bmp(marker.GetBitmap());
            int w = bmp.GetWidth(), h = bmp.GetHeight();
            // FIXME - add scaling and shifting later - maybe
            int i0 = m_owner->GetClientCoordFromPlotX(x0);
            int j0 = m_owner->GetClientCoordFromPlotY(y0);
            dc->DrawBitmap(bmp, RINT(i0 - w/2.0), RINT(j0 - h/2.0), true);
        }
        else if (marker_type == wxPLOTMARKER_LINE)
        {
            if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
            {
                int i0 = m_owner->GetClientCoordFromPlotX(x0);
                int j0 = m_owner->GetClientCoordFromPlotY(y0);
                int i1 = m_owner->GetClientCoordFromPlotX(x1);
                int j1 = m_owner->GetClientCoordFromPlotY(y1);
                wxPLOTCTRL_DRAW_LINE(dc, window, pen, i0, j0, i1, j1);
            }
        }
        else if (marker_type == wxPLOTMARKER_ELLIPSE)
        {
            // fixed pixel size
            if ((size.x > 0) && (size.y > 0))
            {
                if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
                {
                    int i0 = m_owner->GetClientCoordFromPlotX(x0);
                    int j0 = m_owner->GetClientCoordFromPlotY(y0);
                    wxPLOTCTRL_DRAW_ELLIPSE(dc, window, pen, i0, j0, size.x, size.y);
                }
            }
/*
            else if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
            {
                int i0 = m_owner->GetClientCoordFromPlotX(x0);
                int j0 = m_owner->GetClientCoordFromPlotY(y0);
                int i1 = m_owner->GetClientCoordFromPlotX(x1);
                int j1 = m_owner->GetClientCoordFromPlotY(y1);
                wxPLOTCTRL_DRAW_ELLIPSE(dc, window, pen, i0, j0, i1, j1);
            }
*/
        }
        else // figure out the rest
        {
            // we may ignore type if rect is in certain states

            bool is_horiz = r.m_width  < 0;
            bool is_vert  = r.m_height < 0;

            bool cross = is_horiz && is_vert;

            if (is_horiz)
            {
                x0 = subViewRect.m_x - subViewRect.m_width; // push outside win
                x1 = subViewRect.GetRight() + subViewRect.m_width;
            }
            if (is_vert)
            {
                y0 = subViewRect.m_y - subViewRect.m_height;
                y1 = subViewRect.GetBottom() + subViewRect.m_height;
            }

            if ((marker_type == wxPLOTMARKER_POINT) || ((x0 == x1) && (y0 == y1)))
            {
                if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
                {
                    int i0 = m_owner->GetClientCoordFromPlotX(x0);
                    int j0 = m_owner->GetClientCoordFromPlotY(y0);
                    dc->DrawPoint(i0, j0);
                }
            }
            else if ((marker_type == wxPLOTMARKER_VERT_LINE) || ((x0 == x1) && (y0 != y1)))
            {
                if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
                {
                    int i0 = m_owner->GetClientCoordFromPlotX(x0);
                    int j0 = m_owner->GetClientCoordFromPlotY(y0);
                    int j1 = m_owner->GetClientCoordFromPlotY(y1);
                    wxPLOTCTRL_DRAW_LINE(dc, window, pen, i0, j0, i0, j1);
                }
            }
            else if ((marker_type == wxPLOTMARKER_HORIZ_LINE) || ((y0 == y1) && (x0 != x1)))
            {
                if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut)
                {
                    int i0 = m_owner->GetClientCoordFromPlotX(x0);
                    int i1 = m_owner->GetClientCoordFromPlotX(x1);
                    int j0 = m_owner->GetClientCoordFromPlotY(y0);
                    wxPLOTCTRL_DRAW_LINE(dc, window, pen, i0, j0, i1, j0);
                }
            }
            else if ((marker_type == wxPLOTMARKER_CROSS) || cross)
            {


            }
            else                                // rectangle
            {
                wxRect2DDouble clippedRect(x0, y0, x1 - x0, y1 - y0);
                clippedRect.Intersect(subViewRect);
                int pen_width = dc->GetPen().GetWidth() + 2;

                int i0 = m_owner->GetClientCoordFromPlotX(clippedRect.m_x);
                int i1 = m_owner->GetClientCoordFromPlotX(clippedRect.GetRight());
                int j0 = m_owner->GetClientCoordFromPlotY(clippedRect.m_y);
                int j1 = m_owner->GetClientCoordFromPlotY(clippedRect.GetBottom());
                if (r.m_x < subViewRect.m_x)  i0 -= pen_width;
                if (r.m_y < subViewRect.m_y)  j0 -= pen_width;
                if (r.GetRight()  > subViewRect.GetRight())  i1 += pen_width;
                if (r.GetBottom() > subViewRect.GetBottom()) j1 += pen_width;

                dc->SetClippingRegion(dcRect);
                dc->DrawRectangle(i0, j0, i1 - i0 + 1, j1 - j0 + 1);
                dc->DestroyClippingRegion();
            }
        }
    }
}
Exemple #5
0
void wxPlotDrawerDataCurve::Draw(wxDC *dc, wxPlotData* curve, int curve_index)
{
    wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve"));
    INITIALIZE_FAST_GRAPHICS

    wxRect dcRect(GetDCRect());

    wxRect2DDouble viewRect( GetPlotViewRect() ); //m_viewRect );
    wxRect2DDouble subViewRect( m_owner->GetPlotRectFromClientRect(dcRect) );
    wxRect2DDouble curveRect( curve->GetBoundingRect() );
    if (!wxPlotRect2DDoubleIntersects(curveRect, subViewRect)) return;

/*  // FIXME - drawing symbol bitmaps in MSW is very slow
    wxBitmap bitmap;
    if (curve == GetActiveCurve())
        bitmap = curve->GetSymbol(wxPLOTPEN_ACTIVE);
    else
        bitmap = curve->GetSymbol(wxPLOTPEN_NORMAL);

    if (!bitmap.Ok())
    {
        if (curve == GetActiveCurve())
            bitmap = wxPlotSymbolCurrent;
        else
            bitmap = wxPlotSymbolNormal;
    }

    int bitmapHalfWidth = bitmap.GetWidth()/2;
    int bitmapHalfHeight = bitmap.GetHeight()/2;
*/

    // find the starting and ending indexes into the data curve
    int n, n_start, n_end;
    bool x_ordered = curve->GetIsXOrdered();

    if (x_ordered)
    {
        n_start = curve->GetIndexFromX(subViewRect.GetLeft(), wxPlotData::index_floor);
        n_end   = curve->GetIndexFromX(subViewRect.GetRight(), wxPlotData::index_ceil);
        n_end++; // for statement comparison is <
    }
    else
    {
        n_start = 0;
        n_end   = curve->GetCount();
    }

    // set the pens to draw with
    wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen()
                                                                  : curve->GetPen(wxPLOTPEN_NORMAL).GetPen();
    wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen();
    if (m_pen_scale != 1)
    {
        currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale));
        selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale));
    }

    dc->SetPen(currentPen);

    // handle the selected ranges and initialize the starting range
    const wxArrayRangeInt &ranges = m_owner->GetDataCurveSelection(curve_index)->GetRangeArray();
    int n_range = 0, range_count = ranges.GetCount();
    int min_sel = -1, max_sel = -1;
    for (n_range=0; n_range<range_count; n_range++)
    {
        const wxRangeInt& range = ranges[n_range];
        if ((range.m_max >= n_start) || (range.m_min >= n_start))
        {
            min_sel = range.m_min;
            max_sel = range.m_max;
            if (range.Contains(n_start))
                dc->SetPen( selectedPen );

            break;
        }
    }

    // data variables
    const double *x_data = &curve->GetXData()[n_start];
    const double *y_data = &curve->GetYData()[n_start];

    int i0, j0, i1, j1;        // curve coords in pixels
    double x0, y0, x1, y1;     // original curve coords
    double xx0, yy0, xx1, yy1; // clipped curve coords

    x0 = *x_data;
    y0 = *y_data;

    int clipped = ClippedNeither;

    bool draw_lines   = m_owner->GetDrawLines();
    bool draw_symbols = m_owner->GetDrawSymbols();
    bool draw_spline  = m_owner->GetDrawSpline();

    SplineDrawer sd;
    wxRangeDoubleSelection dblRangeSel;

    if (draw_spline)
    {
        wxRangeDouble viewRange(viewRect.m_x, viewRect.GetRight());
        wxRangeDouble dcRange(dcRect.x, dcRect.GetRight());

        for (int r = n_range; r < range_count; r++)
        {
            wxRangeDouble plotRange(curve->GetXValue(ranges[r].m_min),
                                    curve->GetXValue(ranges[r].m_max));

            if (viewRange.Intersects(plotRange))
            {
                double min_x = m_owner->GetClientCoordFromPlotX(plotRange.m_min);
                double max_x = m_owner->GetClientCoordFromPlotX(plotRange.m_max);
                dblRangeSel.SelectRange(wxRangeDouble(min_x, max_x));
            }
            else
                break;
        }

        // spline starts 2 points back for smoothness
        int s_start = n_start > 1 ? -2 : n_start > 0 ? -1 : 0;
        sd.Create(dc, currentPen, selectedPen,
                  wxRect2DDouble(dcRect.x, dcRect.y, dcRect.width, dcRect.height),
                  &dblRangeSel,
                  m_owner->GetClientCoordFromPlotX(x_data[s_start]),
                  m_owner->GetClientCoordFromPlotY(y_data[s_start]),
                  m_owner->GetClientCoordFromPlotX(x_data[s_start+1]),
                  m_owner->GetClientCoordFromPlotY(y_data[s_start+1]));
    }

    for (n = n_start; n < n_end; n++)
    {
        x1 = *x_data++;
        y1 = *y_data++;

        if (draw_spline)
            sd.DrawSpline(m_owner->GetClientCoordFromPlotX(x1),
                          m_owner->GetClientCoordFromPlotY(y1));

        xx0 = x0; yy0 = y0; xx1 = x1; yy1 = y1;
        clipped = ClipLineToRect(xx0, yy0, xx1, yy1, viewRect);
        if (clipped != ClippedOut)
        {
            i0 = m_owner->GetClientCoordFromPlotX(xx0);
            j0 = m_owner->GetClientCoordFromPlotY(yy0);
            i1 = m_owner->GetClientCoordFromPlotX(xx1);
            j1 = m_owner->GetClientCoordFromPlotY(yy1);

            if (draw_lines && ((i0 != i1) || (j0 != j1)))
            {
                wxPLOTCTRL_DRAW_LINE(dc, window, pen, i0, j0, i1, j1);
            }

            if (n == min_sel)
                dc->SetPen( selectedPen );

            if (draw_symbols && !((clipped & ClippedSecond) != 0) &&
                ((i0 != i1) || (j0 != j1) || (n == min_sel) || (n == n_start)))
            {
                //dc->DrawBitmap( bitmap, i1 - bitmapHalfWidth, j1 - bitmapHalfHeight, true );
                wxPLOTCTRL_DRAW_ELLIPSE(dc, window, pen, i1, j1, 2, 2);
            }
        }
        else if (n == min_sel)
        {
            dc->SetPen( selectedPen );
        }

        if (n == max_sel)
        {
            dc->SetPen( currentPen );
            if (n_range < range_count - 1)
            {
                n_range++;
                min_sel = ranges[n_range].m_min;
                max_sel = ranges[n_range].m_max;
            }
        }

        x0 = x1;
        y0 = y1;
    }

    if (draw_spline)
    {
        // want an extra point at the end to smooth it out
        if (n_end < (int)curve->GetCount() - 1)
            sd.DrawSpline(m_owner->GetClientCoordFromPlotX(*x_data),
                          m_owner->GetClientCoordFromPlotY(*y_data));

        sd.EndSpline();
    }

    dc->SetPen(wxNullPen);
}
Exemple #6
0
void wxPlotDrawerCurve::Draw(wxDC *dc, wxPlotCurve *curve, int curve_index)
{
    wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve"));
    INITIALIZE_FAST_GRAPHICS

    wxRect dcRect(GetDCRect());

    int i, j0, j1;
    double x0, y0, x1, y1, yy0, yy1;
    x0 = m_owner->GetPlotCoordFromClientX(0);
    y0 = yy0 = curve->GetY(x0);

    wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect );

    int right = dcRect.GetRight();

    wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen()
                                                                  : curve->GetPen(wxPLOTPEN_NORMAL).GetPen();
    wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen();

    if (m_pen_scale != 1)
    {
        currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale));
        selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale));
    }

    dc->SetPen(currentPen);

    const wxRangeDoubleSelection *ranges = m_owner->GetCurveSelection(curve_index);
    bool selected = false;

    int clipped = ClippedNeither;

    for (i=dcRect.x; i<right; i++)
    {
        x1 = m_owner->GetPlotCoordFromClientX(i);
        y1 = yy1 = curve->GetY(x1);

        clipped = ClipLineToRect(x0, yy0, x1, yy1, subViewRect);

        if (selected != ranges->Contains(x1))
        {
            if (selected)
                dc->SetPen(currentPen);
            else
                dc->SetPen(selectedPen);

            selected = !selected;
        }

        if (clipped != ClippedOut)
        {
            j0 = m_owner->GetClientCoordFromPlotY(yy0);
            j1 = m_owner->GetClientCoordFromPlotY(yy1);
            wxPLOTCTRL_DRAW_LINE(dc, window, pen, i-1, j0, i, j1);

            if (selected && !((clipped & ClippedSecond) != 0))
            {
                wxPLOTCTRL_DRAW_ELLIPSE(dc, window, pen, i, j1, 2, 2);
            }
        }

        x0 = x1;
        y0 = yy0 = y1;
    }

    dc->SetPen(wxNullPen);
}
Exemple #7
0
void wxPlotDrawerKey::Draw(wxDC *dc, const wxString& keyString_)
{
    wxCHECK_RET(dc && m_owner, wxT("Invalid dc"));

    if (keyString_.IsEmpty())
        return;

    wxString keyString = keyString_;

/*
    // GTK - kills X if font size is too small
    double x_scale = 1, y_scale = 1;
    dc->GetUserScale( &x_scale, &y_scale );

    wxFont font = m_owner->GetKeyFont();
    if (0 && x_scale != 1)
    {
        font.SetPointSize(wxMax(int(font.GetPointSize()/x_scale), 4));
        if (!font.Ok())
            font = GetKeyFont();
    }
*/

    wxFont keyFont = m_font;
    if (m_font_scale != 1)
        keyFont.SetPointSize( wxMax(2, RINT(keyFont.GetPointSize() * m_font_scale)) );

    int key_line_width  = RINT(m_key_line_width  * m_pen_scale);
    int key_line_margin = RINT(m_key_line_margin * m_pen_scale);

    dc->SetFont(keyFont);
    dc->SetTextForeground(m_fontColour.GetColour());

    wxRect keyRect;
    int heightLine = 0;

    dc->GetMultiLineTextExtent(keyString, &keyRect.width, &keyRect.height, &heightLine);

    wxRect dcRect(GetDCRect());
    wxSize areaSize = dcRect.GetSize();

    keyRect.x = 30 + int((m_keyPosition.x*.01)*areaSize.x);
    keyRect.y = areaSize.y - int((m_keyPosition.y*.01)*areaSize.y);

    if (m_key_inside)
    {
        keyRect.x = wxMax(30, keyRect.x);
        keyRect.x = wxMin(areaSize.x - keyRect.width - m_border, keyRect.GetRight());

        keyRect.y = wxMax(m_border, keyRect.y);
        keyRect.y = wxMin(areaSize.y - keyRect.height - m_border, keyRect.y);
    }

    int h = keyRect.y;
    int i = 0;

    while (!keyString.IsEmpty())
    {
        wxString subkey = keyString.BeforeFirst(wxT('\n')).Strip(wxString::both);
        keyString = keyString.AfterFirst(wxT('\n'));
        if (subkey.IsEmpty()) break;

        if (m_owner && m_owner->GetCurve(i))
        {
            wxPen keyPen = m_owner->GetCurve(i)->GetPen(wxPLOTPEN_NORMAL).GetPen();
            if (m_pen_scale != 1)
                keyPen.SetWidth(int(keyPen.GetWidth() * m_pen_scale));

            if(keyPen.GetWidth() < 3) keyPen.SetWidth(3);
            dc->SetPen(keyPen);
            dc->DrawLine(keyRect.x - (key_line_width + key_line_margin), h + heightLine/2,
                        keyRect.x - key_line_margin, h + heightLine/2);
        }

        dc->DrawText(subkey, keyRect.x, h);

        h += heightLine;
        i++;
    }

    dc->SetPen(wxNullPen);
    dc->SetFont(wxNullFont);
}