From 32151f8d9478814b80be266ad67fcae1af5ef7d8 Mon Sep 17 00:00:00 2001 From: tslediter Date: Sun, 4 Feb 2024 14:53:12 +0800 Subject: [PATCH] =?UTF-8?q?=E7=95=8C=E9=9D=A2=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化绘图 --- funcext/tvclib/ugtkinterface.tsf | 293 ++- funcext/tvclib/utslvclauxiliary.tsf | 39 +- funcext/tvclib/utslvclgdi.tsf | 164 +- funcext/tvclib/utslvcltree.tsf | 20 +- funcext/tvclib/utvclgraphics.tsf | 2904 +++++++++++++++++++-------- 5 files changed, 2335 insertions(+), 1085 deletions(-) diff --git a/funcext/tvclib/ugtkinterface.tsf b/funcext/tvclib/ugtkinterface.tsf index e4fb913..087cc40 100644 --- a/funcext/tvclib/ugtkinterface.tsf +++ b/funcext/tvclib/ugtkinterface.tsf @@ -773,6 +773,7 @@ type tsgtkapi = class(tgtkapis) r := gtk_object_get_data(hdc,"brush"); gtk_object_set_data(hdc,"brush",gdiobj); gtk_object_set_data(hdc,"brush.color",o.color); + gtk_object_set_data(hdc,"brush.style",o.style); end "font": begin @@ -1092,6 +1093,59 @@ type tsgtkapi = class(tgtkapis) gtk_object_set_data(dc,"pen.width",pw); return 1; end + end + function cairo_set_pen_color(dc); + begin + pc := gtk_object_get_data(dc,"pen.color"); + pt := gtk_object_get_data(dc,"pen.style"); + if pw>0 then cairo_set_line_width(dc,pw); + else cairo_set_line_width(dc,1); + if pc=0 then + begin + if pt=5 then + begin + cairo_set_source_rgba(dc,1,1,1,0); + end else + begin + cairo_set_source_rgb(dc,0,0,0); + end + end else + begin + + if pt=5 then + begin + cairo_set_source_rgba(dc,1,1,1,0); + end else + begin + gtk_rgb_color_rgb(pc,rc,gc,bc); + cairo_set_source_rgb(dc,rc,gc,bc); + end + end + end + function cairo_set_brush_color(dc); + begin + brc := gtk_object_get_data(dc,"brush.color"); + bst := gtk_object_get_data(dc,"brush.style"); + if brc=0 then + begin + if bst=1 then + begin + cairo_set_source_rgba(dc,1,1,1,0); + end else + begin + cairo_set_source_rgb(dc,0,0,0); + end + end else + begin + if bst=1 then + begin + cairo_set_source_rgba(dc,1,1,1,0); + end else + begin + gtk_rgb_color_rgb(brc,rc,gc,bc); + cairo_set_source_rgb(dc,rc,gc,bc); + end + end end Function FillRect(dc:pointer;rec:array of integer;br:pointer):integer; @@ -1239,6 +1293,18 @@ type tsgtkapi = class(tgtkapis) gtk_gdi_object_globals[inttostr(ptr)] := array(p,"brush"); return ptr; end + function CreateBrushIndirect(lblf:pointer); + begin + global gtk_gdi_object_globals; + p := new ttgtk_brush(); + p2 := new ttgtk_brush(lblf); + p.color := p2.color; + p.style := p2.style; + //p.color := crColor; + ptr := p._getptr_(); + gtk_gdi_object_globals[inttostr(ptr)] := array(p,"brush"); + return ptr; + end function CreateFontIndirectA(lplf:pointer); begin global gtk_gdi_object_globals; @@ -1269,20 +1335,11 @@ type tsgtkapi = class(tgtkapis) Function LineTo(dc :pointer;x:integer;y:integer):integer; begin xb := gtk_object_get_data(dc,"viewport.x"); - yb := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + yb := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); - pt := gtk_object_get_data(dc,"pen.style"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_applay_pen_style(dc); //LineTo xy := gtk_object_get_data(dc,"movepointto"); if xy then @@ -1504,10 +1561,8 @@ type tsgtkapi = class(tgtkapis) Function Rectangle(dc :pointer;l:integer;t:integer;r:integer;b:integer):integer; begin x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); - brc := gtk_object_get_data(dc,"brush.color"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); if pc=0 then @@ -1525,23 +1580,9 @@ type tsgtkapi = class(tgtkapis) cairo_line_to(dc,l+x,b+y); cairo_line_to(dc,l+x,t+y); - if brc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(brc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_brush_color(dc); cairo_fill_preserve(dc); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); return 1; @@ -1551,10 +1592,8 @@ type tsgtkapi = class(tgtkapis) //Ô²ÐÄ //³¤¶È x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); - brc := gtk_object_get_data(dc,"brush.color"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); mx := (l+r)/2+x; @@ -1565,23 +1604,9 @@ type tsgtkapi = class(tgtkapis) cairo_scale(dc,1,ry/rx); cairo_applay_pen_style(dc); cairo_arc(dc, 0, 0, rx, 0, 2 * pi()); - if brc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(brc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_brush_color(dc); cairo_fill_preserve(dc); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); cairo_scale(dc,1,rx/ry); cairo_translate(dc,0-mx,0-my); @@ -1590,37 +1615,24 @@ type tsgtkapi = class(tgtkapis) Function RoundRect(dc :pointer;l:integer;t:integer;r:integer;b:integer;wid:integer;ht:integer):integer; begin xb := gtk_object_get_data(dc,"viewport.x"); - yb := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + yb := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); cairo_applay_pen_style(dc); cairo_draw_round_rectangle(dc,l,t,r-l,b-t,wid); - - bsh := gtk_object_get_data(dc,"brush.color"); - gtk_rgb_color_rgb(bsh,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); + cairo_set_brush_color(dc); cairo_fill_preserve(dc); //»æÖƵ×É« - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc);//»æÖƱ߿ò return 1; end Function Chord(hdc :pointer;l:integer;t:integer;r:integer;b:integer;wid:integer;ht:integer):integer; begin x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); - brc := gtk_object_get_data(dc,"brush.color"); direct := gtk_object_get_data(dc,"arcdirection"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); @@ -1646,25 +1658,11 @@ type tsgtkapi = class(tgtkapis) cairo_arc(dc, 0, 0, rx, arg2, arg1); end - if brc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(brc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_brush_color(dc); cairo_move_to(dc,cos(arg1)*rx,sin(arg1)*rx); cairo_line_to(dc,cos(arg2)*rx,sin(arg2)*rx); cairo_fill_preserve(dc); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); cairo_scale(dc,1,rx/ry); @@ -1673,10 +1671,8 @@ type tsgtkapi = class(tgtkapis) Function Pie(dc :pointer;l:integer;t:integer;r:integer;b:integer;nXRadial1:integer;nYRadial1:integer;nXRadial2:integer;nYRadial2:integer):integer; begin x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); - brc := gtk_object_get_data(dc,"brush.color"); direct := gtk_object_get_data(dc,"arcdirection"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); @@ -1701,27 +1697,12 @@ type tsgtkapi = class(tgtkapis) begin cairo_arc(dc, 0, 0, rx, arg2, arg1); end - - if brc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(brc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_brush_color(dc); cairo_move_to(dc,cos(arg1)*rx,sin(arg1)*rx); cairo_line_to(dc,0,0); cairo_line_to(dc,cos(arg2)*rx,sin(arg2)*rx); cairo_fill_preserve(dc); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); cairo_scale(dc,1,rx/ry); @@ -1775,8 +1756,7 @@ type tsgtkapi = class(tgtkapis) Function Arc(dc :pointer;l:integer;t:integer;r:integer;b:integer;nXRadial1:integer;nYRadial1:integer;nXRadial2:integer;nYRadial2:integer):integer; begin x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); //brc := gtk_object_get_data(dc,"brush.color"); direct := gtk_object_get_data(dc,"arcdirection"); @@ -1812,14 +1792,7 @@ type tsgtkapi = class(tgtkapis) cairo_set_source_rgb(dc,rc,gc,bc); end cairo_fill_preserve(dc); } - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); cairo_scale(dc,1,rx/ry); cairo_translate(dc,0-mx,0-my); @@ -1828,9 +1801,7 @@ type tsgtkapi = class(tgtkapis) begin if n<3 then return ; x := gtk_object_get_data(dc,"viewport.x"); - y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); - brc := gtk_object_get_data(dc,"brush.color"); + y := gtk_object_get_data(dc,"viewport.y"); pw := gtk_object_get_data(dc,"pen.width"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); @@ -1842,23 +1813,9 @@ type tsgtkapi = class(tgtkapis) cairo_line_to(dc,Points[i,0]+x,Points[i,1]+y); end cairo_line_to(dc,Points[0,0]+x,Points[0,1]+y); - if brc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(brc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_brush_color(dc); cairo_fill_preserve(dc); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_stroke(dc); end Function PolyBezier(dc :pointer;points:array of integer;n:integer):integer; @@ -1866,18 +1823,10 @@ type tsgtkapi = class(tgtkapis) if length(points)<4 then return 0; x := gtk_object_get_data(dc,"viewport.x"); y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); pw := gtk_object_get_data(dc,"pen.width"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_applay_pen_style(dc); cairo_move_to(dc,points[0,0]+x,Points[0,1]+y); for i := 1 to length(points)-2 step 3 do @@ -1896,18 +1845,10 @@ type tsgtkapi = class(tgtkapis) if n<2 then return ; x := gtk_object_get_data(dc,"viewport.x"); y := gtk_object_get_data(dc,"viewport.y"); - pc := gtk_object_get_data(dc,"pen.color"); pw := gtk_object_get_data(dc,"pen.width"); if pw>0 then cairo_set_line_width(dc,pw); else cairo_set_line_width(dc,1); - if pc=0 then - begin - cairo_set_source_rgb(dc,0,0,0); - end else - begin - gtk_rgb_color_rgb(pc,rc,gc,bc); - cairo_set_source_rgb(dc,rc,gc,bc); - end + cairo_set_pen_color(dc); cairo_applay_pen_style(dc); for i := 0 to n-1 do begin @@ -4613,7 +4554,7 @@ type tgtkapis = class() //gtk return ##_f_(c); end //procedure draw_round_rectangle(c:pointer;x:double;y:double;w:double;h:double;r:double);cdecl;external 'libgtk-3.so'; - procedure cairo_arc (cr:pointer; xc:double;yc:double;radius:double;angle1:double;angle2:double); + procedure cairo_arc(cr:pointer; xc:double;yc:double;radius:double;angle1:double;angle2:double); begin _f_ := static procedure(cr:pointer; xc:double;yc:double;radius:double;angle1:double;angle2:double);cdecl;external getfuncptrbyname(0,functionname()); return ##_f_(cr,xc,yc,radius,angle1,angle2); @@ -4736,27 +4677,47 @@ type tgtkapis = class() //gtk function cairo_applay_pen_style(dc); begin pt := gtk_object_get_data(dc,"pen.style"); - if pt=0x2 or pt=0x3 or pt=0x4 then - begin - cairo_set_dash(dc,array(4.0,1.0),2,0); + case pt of + 1: + begin + ds := array(14,6); + cairo_set_dash(dc,ds,length(ds),0); + end + 2: + begin + ds := array(3,3); + cairo_set_dash(dc,ds,length(ds),0); + end + 3: + begin + ds := array(10,4,3,4); + cairo_set_dash(dc,ds,length(ds),0); + end + 4: + begin + ds := array(10,3,3,3,3,3); + cairo_set_dash(dc,ds,length(ds),0); + end else + begin + cairo_set_dash(dc,array(0),0,0); + end end - else cairo_set_dash(dc,array(4.0,0.0),2,0); return pt=5; end function cairo_draw_round_rectangle(cr,x,y,w,h,r); begin - cairo_move_to (cr, x + r, y); - cairo_line_to (cr, x + w - r, y); - cairo_move_to (cr, x + w, y + r); - cairo_line_to (cr, x + w, y + h - r); - cairo_move_to (cr, x + w - r, y + h); - cairo_line_to (cr, x + r, y + h); - cairo_move_to (cr, x, y + h - r); - cairo_line_to (cr, x, y + r); - cairo_arc (cr, x + r, y + r, r, 3.14, 3 * 3.14 / 2.0); - cairo_arc (cr, x + w - r, y + r, r, 3 * 3.14 / 2, 2 * 3.14); - cairo_arc (cr, x + w - r, y + h - r, r, 0, 3.14 / 2); - cairo_arc (cr, x + r, y + h - r, r, 3.14 / 2, 3.14); + cairo_move_to(cr, x + r, y); + cairo_line_to(cr, x + w - r, y); + cairo_move_to(cr, x + w, y + r); + cairo_line_to(cr, x + w, y + h - r); + cairo_move_to(cr, x + w - r, y + h); + cairo_line_to(cr, x + r, y + h); + cairo_move_to(cr, x, y + h - r); + cairo_line_to(cr, x, y + r); + cairo_arc(cr, x + r, y + r, r, 3.14, 3 * 3.14 / 2.0); + cairo_arc(cr, x + w - r, y + r, r, 3 * 3.14 / 2, 2 * 3.14); + cairo_arc(cr, x + w - r, y + h - r, r, 0, 3.14 / 2); + cairo_arc(cr, x + r, y + h - r, r, 3.14 / 2, 3.14); end //////////////////////text//////// https://developer.gnome.org/cairo/stable/cairo-cairo-font-options-t.html#cairo-font-options-get-hint-metrics procedure cairo_show_text(c:pointer;t:string); diff --git a/funcext/tvclib/utslvclauxiliary.tsf b/funcext/tvclib/utslvclauxiliary.tsf index f98c946..cba0a25 100644 --- a/funcext/tvclib/utslvclauxiliary.tsf +++ b/funcext/tvclib/utslvclauxiliary.tsf @@ -1554,6 +1554,16 @@ type TNode = class() // if idx >= 0 then return FItems[idx]; return nil; end + function set_node_index(nd,idx); //ÉèÖÃ×ÓÏî´ÎÐò + begin + if not(idx>=0) then return -1; + oidx := FItems.indexof(v); + if oidx>=0 and idx<>oidx then + begin + setorder(oidx,idx); + end else return 0; + return 1; + end function indexof(v); //»ñµÃÐòºÅ begin return FItems.indexof(v); @@ -1624,9 +1634,9 @@ type TNode = class() // if not nd then return; //ÊÇ·ñÏÔʾ´¦Àí FItems.Deli(idx); - CurrentDeleteNode := nd; + FCurrentDeleteNode := nd; nd.parent := self(true); - CurrentDeleteNode := nil; + FCurrentDeleteNode := nil; return true; end function DeleteChildren();virtual; // @@ -1638,9 +1648,9 @@ type TNode = class() // begin idx := 0; it := FItems[idx]; - CurrentDeleteNode := it; + FCurrentDeleteNode := it; it.parent := self(true); - CurrentDeleteNode := nil; + FCurrentDeleteNode := nil; FItems.Deli(idx); end end @@ -1660,9 +1670,9 @@ type TNode = class() // if(it is class(TNode))and(not it.Parent)then begin FItems.InsertBefor(it,idx0); - CurrentAddNode := it; + FCurrentAddNode := it; it.Parent := self(true); - CurrentAddNode := nil; + FCurrentAddNode := nil; idx0++; end end @@ -1680,9 +1690,9 @@ type TNode = class() // if idx>FItems.Count then idx := FItems.Count; if not(idx >= 0)then idx := 0; FItems.InsertBefor(it,idx); - CurrentAddNode := it; + FCurrentAddNode := it; it.Parent := self(true); - CurrentAddNode := nil; + FCurrentAddNode := nil; return true; end end @@ -1726,15 +1736,20 @@ type TNode = class() // @param(Parent)(TNode) ¸¸½Úµã %% **} protected - property CurrentDeleteNode read FCurrentDeleteNode write FCurrentDeleteNode; - property CurrentAddNode read FCurrentAddNode write FCurrentAddNode; + property CurrentDeleteNode read FCurrentDeleteNode; + property CurrentAddNode read FCurrentAddNode; {** @ignoremembers(CurrentDeleteNode,CurrentAddNode) **} function SetParent(V);virtual; begin tp := Parent; - if v=tp then return; + if tp and (v=tp) and( v.CurrentDeleteNode=self ) then + begin + FParent := nil; + return; + end + if (v=tp) then return; if(v is class(TNode))then begin if v.CurrentAddNode=self then @@ -1759,6 +1774,8 @@ type TNode = class() // end end private + fwilldelete; + fwilladd; function GetLstChild(); begin return FItems[FItems.Count-1]; diff --git a/funcext/tvclib/utslvclgdi.tsf b/funcext/tvclib/utslvclgdi.tsf index d1ba25e..b9193c2 100644 --- a/funcext/tvclib/utslvclgdi.tsf +++ b/funcext/tvclib/utslvclgdi.tsf @@ -611,6 +611,14 @@ type tcustombrush=class(tgdi) FColor := c; end end + function SetStyle(s); + begin + if (s <> FStyle) and (s in array(BS_SOLID,BS_NULL)) then + begin + onchange(); + FStyle := s; + end + end public class function sinit();override; begin @@ -637,11 +645,11 @@ type tcustombrush=class(tgdi) hp := reference(); if not hp then begin - //LOGSTRUCT._setvalue_("lbstyle",FStyle); - //LOGSTRUCT._setvalue_("lbcolor",FColor); + LOGSTRUCT._setvalue_("lbstyle",FStyle); + LOGSTRUCT._setvalue_("lbcolor",FColor); //LOGSTRUCT._setvalue_("lbhatch",FHatch); - //hp := _wapi.CreateBrushIndirect(LOGSTRUCT._getptr_); - hp := _wapi.CreateSolidBrush(FColor); + hp := _wapi.CreateBrushIndirect(LOGSTRUCT._getptr_); + //hp := _wapi.CreateSolidBrush(FColor); addsource(hp); end FHandle := hp; @@ -671,7 +679,7 @@ type tcustombrush=class(tgdi) end end end - //property Style read FStyle write SetStyle; + property Style read FStyle write SetStyle; property Color read FColor write SetColor; //property Hatch read FHatch write SetHatch; end @@ -814,59 +822,7 @@ type TRGNRoundRect=class(TRGNELLIP) property EllipseWidth:integer read FEllipseWidth write SetEllipseWidth; property EllipseHeight:integer read FEllipseHeight write SetEllipseHeight; end -type TRGNPOLY=class(TRGN) //¶à±ßÐÎ - {** - @explan(˵Ã÷)¶à±ßÐÎÇøÓò%% - **} - private - FPoints; - FImode; - function pointtovector(pts); //µãת»»ÎªÊý×é - begin - t := array(); - lt := 0; - if not ifarray(pts)then return array(); - for i,v in pts do - begin - if ifarray(v)and ifnumber(v[0])and ifnumber(v[1])then - begin - t[lt++]:= v[0]; - t[lt++]:= v[1]; - end - end - return t; - end - function SetImode(v); - begin - if(v in array(1,2))and v <> FImode then - begin - FImode := v; - DestroyHandle(); - end - end - function SetPoints(v); - begin - if v <> FPoints then - begin - FPoints := v; - DestroyHandle(); - end - end - public - function create(); //µã ºÍÌî³äģʽ - begin - inherited; - FImode := ALTERNATE; - end - function CreateRgn();override; - begin - t := pointtovector(FPoints); - len := length(t); - if len>5 then return _wapi.CreatePolygonRgn(t,len/2,FImode); - end - property Points read FPoints write SetPoints; - property Imode read FImode write SetImode; -end + type tcustomimage=class(TSLUIBASE) {** @@ -3210,11 +3166,10 @@ type tshapechord = class(tshape,tshaperect,tsepoint) return inherited; end end -type tshapepolygon = class(tshape) +type tshapepolygon = class(tshapepolyline) function create(dc); begin inherited; - fbpoints := array(); end function draw();override; begin @@ -3224,6 +3179,22 @@ type tshapepolygon = class(tshape) end return inherited; end + function points(ps);override; + begin + r := inherited; + if length(fbpoints)<2 then + begin + fbpoints := array(); + end + return r; + end +end +type tshapepolyline = class(tshape) + function create(dc); + begin + inherited; + fbpoints := array(); + end function points(ps);virtual; begin tps := array(); @@ -3234,21 +3205,13 @@ type tshapepolygon = class(tshape) tps[idx++] := array(v[0],v[1]); end end - if length(tps)>2 then + if length(tps)>1 then begin fbpoints := tps; end return self(true); end - protected - fbpoints; - -end -type tshapepolyline = class(tshapepolygon) - function create(dc); - begin - inherited; - end + function draw();override; begin if fcanvas and fcanvas.HandleAllocated() and fbpoints then @@ -3256,7 +3219,9 @@ type tshapepolyline = class(tshapepolygon) fcanvas._wapi.polyline(fcanvas.handle,fbpoints,length(fbpoints)); end return self(true); - end + end + protected + fbpoints; end type tshapeBezier = class(tshape) function create(dc); @@ -3415,4 +3380,59 @@ class(tUIglobalData).uisetdata("G_T_BITMAP_",class(TcustomBitmap)); class(tUIglobalData).uisetdata("G_T_ICON_",class(TcustomIcon)); finalization -end. \ No newline at end of file +end. +(* +type TRGNPOLY=class(TRGN) //¶à±ßÐÎ + {** + @explan(˵Ã÷)¶à±ßÐÎÇøÓò%% + **} + private + FPoints; + FImode; + function pointtovector(pts); //µãת»»ÎªÊý×é + begin + t := array(); + lt := 0; + if not ifarray(pts)then return array(); + for i,v in pts do + begin + if ifarray(v)and ifnumber(v[0])and ifnumber(v[1])then + begin + t[lt++]:= v[0]; + t[lt++]:= v[1]; + end + end + return t; + end + function SetImode(v); + begin + if(v in array(1,2))and v <> FImode then + begin + FImode := v; + DestroyHandle(); + end + end + function SetPoints(v); + begin + if v <> FPoints then + begin + FPoints := v; + DestroyHandle(); + end + end + public + function create(); //µã ºÍÌî³äģʽ + begin + inherited; + FImode := ALTERNATE; + end + function CreateRgn();override; + begin + t := pointtovector(FPoints); + len := length(t); + if len>5 then return _wapi.CreatePolygonRgn(t,len/2,FImode); + end + property Points read FPoints write SetPoints; + property Imode read FImode write SetImode; +end +*) \ No newline at end of file diff --git a/funcext/tvclib/utslvcltree.tsf b/funcext/tvclib/utslvcltree.tsf index 54ba016..f73a498 100644 --- a/funcext/tvclib/utslvcltree.tsf +++ b/funcext/tvclib/utslvcltree.tsf @@ -980,9 +980,9 @@ type TcustomTreeCtlNode = class(tsluibase) // Owner.DeleteItemByIndex(Owner.GetItemIndex(nd)); end FItems.Deli(idx); - CurrentDeleteNode := nd; + FCurrentDeleteNode := nd; nd.parent := self(true); - CurrentDeleteNode := nil; + FCurrentDeleteNode := nil; if nd = Owner.CurrentNode then begin Owner.SetSel(nil); @@ -1015,9 +1015,9 @@ type TcustomTreeCtlNode = class(tsluibase) // begin idx := 0; //ItemCount-1; it := FItems[idx]; - CurrentDeleteNode := it; + FCurrentDeleteNode := it; it.parent := self(true); - CurrentDeleteNode := nil; + FCurrentDeleteNode := nil; FItems.Deli(idx); end end @@ -1061,9 +1061,9 @@ type TcustomTreeCtlNode = class(tsluibase) // odexp := it.Expanded; it.UnExpand(); FItems.InsertBefor(it,idx0); - CurrentAddNode := it; + FCurrentAddNode := it; it.Parent := self(true); - CurrentAddNode := nil; + FCurrentAddNode := nil; it.UpDateHierarchy(); nits[nitsi++]:= it; idx0++; @@ -1095,9 +1095,9 @@ type TcustomTreeCtlNode = class(tsluibase) // odexp := it.Expanded; it.UnExpand(); FItems.InsertBefor(it,idx); - CurrentAddNode := it; + FCurrentAddNode := it; it.Parent := self(true); - CurrentAddNode := nil; + FCurrentAddNode := nil; it.UpDateHierarchy(); if Expanded and Owner.NodeInList(self)then begin @@ -1297,8 +1297,8 @@ type TcustomTreeCtlNode = class(tsluibase) // @param(Owner)(TcustomTreeCtl) ËùÓÐÕß %% **} protected //¸¸×Ó½ÚµãÉèÖÃÏà¹Ø - property CurrentDeleteNode read FCurrentDeleteNode write FCurrentDeleteNode; - property CurrentAddNode read FCurrentAddNode write FCurrentAddNode; + property CurrentDeleteNode read FCurrentDeleteNode; + property CurrentAddNode read FCurrentAddNode; FItems; //×ÓÏî [weakref]FParent; //¸¸½Úµã function Gitems(); diff --git a/funcext/tvclib/utvclgraphics.tsf b/funcext/tvclib/utvclgraphics.tsf index 3aee64d..92369eb 100644 --- a/funcext/tvclib/utvclgraphics.tsf +++ b/funcext/tvclib/utvclgraphics.tsf @@ -3,6 +3,109 @@ interface uses utslvclauxiliary; //tsl»æÍ¼¿â //20240126 +//20240204 Ìí¼Ó˵Ã÷ +{ + tg_const ³£Á¿ÀàÐÍ£¬×÷ΪËùÓÐÀàÐ͵ĻùÀ࣬Ìṩ³£Á¿±ðÃû + tg_canvas »æÍ¼»­²¼¶ÔÏ󣬸öÔÏóÒÔ´°¿ÚÖеÄcanvasΪ¸¸À࣬²¢Ôö¼ÓÁ˸¨Öúº¯Êý + axesclip() ÏÞ¶¨µ½×ø±êÏµÇøÓò + axesunclip() È¡Ïû×ø±êÏµÇøÓòÏÞ¶¨ + axesrec ×ø±êϵµÄ·¶Î§ + tg_line_info »­±ÊÏßÐÍÐÅÏ¢ + Style ÏßÐÍ tgc_PS_DOT tgc_PS_DASH tgc_PS_NULL tgc_PS_SOLID tgc_PS_DASHDOT tgc_PS_DASHDOTDOT + size Ïß¿í¶È£¬ÏñËØ + color ÏßÑÕÉ« + bkcolor ÏßÐÍ·â±ÕºóµÄ±³¾° + tg_font_info ϵͳÐÅÏ¢ + size ×ֺţ¬¿í¶ÈµÄÏñËØ + color ×ÖÑÕÉ« + bkcolor ±³¾°É« + tg_mark_info µã±ê¼ÇÐÅÏ¢ + size ±ê¼Ç´óС£¬ÏñËØ + color ÏßÑÕÉ« + bkcolor ±³¾°É« + + tg_base ×ö¸ö»æÍ¼Àà»ùÀ࣬ÌṩһЩ»ù´¡¹¦ÄÜ£¬ÒÔ¼°²ã´Î¹ØÏµ + ²ã´Î¹ØÏµ£º + parent: ÉèÖûòÕ߸¸½Úµã + nodecount »ñÈ¡×Ó½ÚµãÊýÁ¿ + GetNodeByIndex ͨ¹ýÐòºÅ»ñÈ¡×Ó½Úµã + set_node_index(nd,idx) ÉèÖÃ×Ó½ÚµãµÄÐòºÅ + »ù´¡¹¦ÄÜ£º + markinfo ±ê¼ÇÐÅÏ¢ tg_mark_info ÀàÐÍ + lineinfo »­±ÊÐÅÏ¢ tg_line_info ÀàÐÍ + Coordinate_Mapping(x,y,z,var _x,var _y) ͨ¹ý×ø±êµã¼ÆËã»­²¼µãλÖà + Coordinate_unMapping(x,y,var x_,var y_,var z_) ͨ¹ý»­²¼µã¼ÆËã×ø±êµã + set_lineinfo_to_canvas(cvs,peninfo) ÉèÖõ±Ç°»­±ÊÐÅÏ¢µ½»­²¼ + set_fontinfo_to_canvas(cvs,info) ÉèÖõ±Ç°×ÖÌåÐÅÏ¢µ½»­²¼ + paint(cvs);virtual;¸Ãº¯ÊýÓÉtg_figureµÄ¹ÜÀíÕßÔÚÊʵ±Ê±ºò·¢Æð£¬²¢ËÍÈëtg_canvas¶ÔÏó + + tg_figure //×ø±êÈÝÆ÷À࣬¿ÉÒÔÔÚÉÏÃæ·Å×ø±êϵ£¬ÉèÖÃ×ø±êϵµÄλÖÃÐÅÏ¢ + add_axes(axes) Ìí¼Ó×ø±êϵ + del_axes(axes) ɾ³ý×ø±êϵ + executecommand(cmd,p); //ÃüÁîÐÐÖ´ÐÐ + ÊôÐÔ£º + rec_getter £ºfunction() ·µ»Ø»­²¼ÇøÓò array(×óÉÏÓÒÏÂ) + fresh_caller: function() //ˢлص÷ + tg_axes ×ø±êϵÀàÐÍ£¬×÷Ϊ»æÍ¼µÄ»ù´¡ÔØÌ壬ÒÔ¼°Î»ÖùØÏµµÄ»ù×¼ + ÊôÐÔ£º + title ±êÌâ tg_label ÀàÐÍ + y_label yÖá±êÇ© tg_label ÀàÐÍ + x_label xÖá±êÇ© tg_label ÀàÐÍ + axises(idx) 0,1,2 ·Ö±ð»ñÈ¡¶ÔÓ¦µÄx£¬yÖá £¬tg_axis ÀàÐÍ + axes_reverse(idx) ×ø±êÖáÊÇ·ñ·´Ïò£¬Ä¬ÈÏÕýÏò + auto_ticks(idx) ÉèÖÃ×ø±êÖá¿Ì¶È×Ô¶¯¼ÆËã + margins ¿Õ°×£¬array(×óÉÏÓÒÏÂ)£¬ÉèÖÃÉÏÏÂ×óÓÒ¿Õ°×£¬tg_figureÇøÓòµÄ°Ù·Ö±È + axes_bounds(idx) ×ø±êϵµÄ´óС array((x,width),(y,heigt))£¬ÒÔmarginsΪ»ù×¼µã£¬°²°Ù·Ö±È + data_bounds(idx) »ñÈ¡»òÕßÉèÖÃÊý¾Ý·¶Î§ array((x0,x1),(y0,y1),(z0,z1)) + zoom_box(idx) ÉèÖÃÏÔʾµÄÊý¾ÝµÄÇøÓò array((x0,x1),(y0,y1),(z0,z1)) + x_location ×ø±êÖá·½Ïò£¬tgc_bottom tgc_top,tgc_middle ,tgc_origin + y_location ×ø±êÖá·½Ïò£¬tgc_left tgc_right,tgc_middle ,tgc_origin + box ÊÇ·ñÓб߿ò + grid(idx) ±³¾°Íø¸ñÏßÊôÐÔ tg_line_info ¶ÔÏó£¬sizeΪ0µÄʱºòÍø¸ñÏßÏûʧ + + tg_axis ×ø±êÖᣬ¿ÉÒÔÔÚ×ø±êϵÖзÅÖÃÈÎÒâ¶à¸ö×ø±êÖá + tics_direction ×ø±êÖá·½Ïò tgc_left tgc_right tgc_bottom tgc_top + tics_style ¿Ì¶ÈÀàÐÍ tgc_tics_v (ÉèÖÃÖµ) tgc_tics_r ([x0,x1,inteval]) + xtics_coord ¿Ì¶È£¬¸ù¾Ýtics_style È·¶¨ [2,3,4,5,6,7] ¼ÆËã [start,end,interval] + ytics_coord λÖã¬ÉèÖÃÔÚÁíÒ»¸ö·½ÏòµÄλÖã¬Ïà¶Ô×ø±êϵµÄÊý¾ÝλÖà + tics_segment ÊÇ·ñÓÐÖáÏß + tics_color ¿Ì¶ÈÏßÑÕÉ« + sub_tics ×ӿ̶ȸöÊý + tics_labels ¿Ì¶ÈÖµ¶ÔÓ¦µÄ±êÇ©£¬Ò»Î¬×Ö·û´®Êý×é + + tg_label ±êÇ©£¬ÒÔaxes×÷Ϊ¸¸½Úµã + text Îı¾ + position ×ø±êϵλÖà + auto_position ×Ô¶¯Î»Öã¬ÔÚ×ø±êÖá±êÇ©ÖÐʹÓà + font_angle ÉèÖÃ½Ç¶È + ÆäËû×ÖÌåÏà¹ØµÄͨ¹ý fontinfoÉèÖà + tg_graph_base ͼ»ùÀà + get_data_bounds();virtual; //»ñÈ¡Êý¾Ý±ß½ç + tg_graph ͼÀàÐÍ + get_data_tips(); //»ñµÃÊý¾ÝÌáʾ¶ÔÏó + get_legend_size(var w,var h);virtual; »ñȡͼÀýÖеĴóС + paint_legend(cvs,rec);virtual; //»æÖÆÍ¼Àý + get_graph_data_by_idx(idx); //ͨ¹ýÊý¾ÝÐòºÅ»ñÈ¡Êý¾Ý + graph_data »æÍ¼Êý¾Ý; + + tg_Polyline Ïßͼ£¬ÒÔtg_graphΪ¸¸Àà + closed ÊÇ·ñ·â±ÕµÄͼÏñ + line_mode ÊÇ·ñ»­Ïß + mark_mode ÊÇ·ñ»­µãµÄ±ê¼Ç + polyline_style ÏßÀàÐÍ£¬ tgc_LS_interpolated tgc_LS_bar tgc_LS_filled tgc_LS_arrowed tgc_LS_barplot tgc_LS_staircase + bar_width Öù״ͼÀàÐÍʱºòµÄ¿í¶È + tg_legend ͼÀý + + location λÖà tgc_in_upper_left tgc_in_lower_left ..... tgc_by_coordinates + postion ¶¨Î»Îªtgc_by_coordinates£¬ÉèÖþßÌåλÖà array(x,y) + line_mode ±ß¿òÏß + links ¹ØÁªµÄ»æÍ¼£¬tg_graph Êý×é + texts Îı¾ÄÚÈÝ£¬×Ö·û´®Êý×é + tg_tips Êý¾ÝµãÌáʾ£¬¸¸½ÚµãΪtg_graph ¶ÔÏó + + tg_WinControl:»æÍ¼Õ¹Ê¾´°¿Ú¶ÔÏ󣬹ÜÀíÁËÒ»¸ö tg_figure ¶ÔÏó£¬ÔÚpaintÏûÏ¢µÄʱºò¹¹Ôìtg_canvas ¶ÔÏó²¢µ÷ÓÃtg_figrueµÄpaintº¯ÊýʵÏÖͼÐεĻæÖÆ + Æä½ö½ö×÷Ϊһ¸ö°¸Àý£¬Óû§¿ÉÒÔ°´ÕÕÆäÔ­Àí¹¹Ôì×Ô¼ºµÄ»­²¼¶ÔÏó£¬Çý¶¯»æÖÆ£¬µÃµ½Í¼ÐÎ +} { //////////////////»æÍ¼·¶Àý////////////////////////// uses tslvcl,utvclgraphics; @@ -14,13 +117,13 @@ type tfm = class(tvcform) function create(aowner); begin inherited; - fg := new tcustomfigure(self); + fg := new tg_WinControl(self); fg.Caption := "hello1"; fg.parent := self; fg.Align := alClient; //////////ÉèÖÃ×ø±êÖáÊôÐÔ//////////////////////// axs := new tg_axes(); - axs.figure := fg; + axs.figure := fg.figure; axs.title.text := "ÄãºÃ plot "; axs.title.fontinfo.size := 15; axs.title.fontinfo.color := 0xff0000; @@ -50,26 +153,114 @@ type tfm = class(tvcform) d[idx] := array(i,sin(i)); idx++; end - line.data := d; + line.graph_data := d; line.parent := axs; end fg; end - } -type tcustomfigure = class(tcustomcontrol,tg_const) //»æÍ¼´°¿Ú + +type tg_WinControl = class(tcustomcontrol,tg_const) //»æÍ¼´°¿Ú function create(AOwner); + begin + inherited; + ffigure := new tg_figure(); + fg_timer := new unit(utslvclstdctl).tcustomtimer(self); + fg_timer.Interval := 200; + fg_timer.Ontimer := thisfunction(figure_need_fresh); + ffigureprepared := false; + ffigure.rec_getter := function()begin + return clientrect; + end + ffigure.fresh_caller := thisfunction(flushfigure); + end + function flushfigure(); + begin + if not ffigureprepared then return ; + if Fneed_invaliate then return ; + if not HandleAllocated() then return ; + Fneed_invaliate := true; + fg_timer.start(); + end + function paint();override; //»æÖÆ + begin + cvs := canvas; + ffigure.paint(cvs); + ffigureprepared := true; + end + function DestroyHandle();override; + begin + ffigureprepared := false; + inherited; + end + function DoMouseWheel(o,e);override; + begin + + p1 := ScreenToClient(e.xpos,e.ypos); + ffigure.executecommand("zoom_inc",array("delta":e.delta,"pos":p1)); + end + function DoWMSIZE(o,e);override; + begin + inherited; + ffigure.executecommand("figure_changed"); + end + function Recycling();override; + begin + ffigure:=nil; + inherited; + end + property figure read ffigure; + private + function figure_need_fresh(o,e); //¶¨Ê±Ë¢Ð + begin + o.stop(); + //echo "\r\ninvalidate time:",datetimetostr(now()); + InvalidateRect(nil,false); + Fneed_invaliate := false; + end + private + ffigure; + fg_timer; + Fneed_invaliate; + ffigureprepared; +end +type tg_figure = class() ///////// + function create(); begin inherited; faxeses := new tnumindexarray(); end - function paint();override; //»æÖÆ + function paint(cvs); //»æÖÆ begin + cvs := new tg_canvas(cvs.Handle); for i,v in faxeses.data do begin - v.axes_paint_rect_changd(); - v.paint(canvas); - end + v.paint_pre(cvs); + end + end + function executecommand(cmd,p); + begin + case cmd of + "figure_need_fresh": + begin + fresh(); + return ; + end + "zoom_inc": + begin + for i,v in faxeses.data do + begin + v.executecommand("zoom_inc",p); + end + end + "figure_changed": + begin + for i,v in faxeses.data do + begin + v.executecommand("figure_changed"); + end + end + end ; end function add_axes(axs);//Ìí¼Ó begin @@ -98,15 +289,19 @@ type tcustomfigure = class(tcustomcontrol,tg_const) // end fwilldelaxs := axs; axs.figure := nil; - end - function Recycling();override; + end + function fresh(); /////////////////////////// begin - for i,v in faxeses.data do - begin - v.figure := nil; - end - inherited; + if ffresh_caller then call(ffresh_caller); end + function rect(); ////////////////////////////////// + begin + r := array(0,0,200,200); + if frect_getter then r := call(frect_getter); + return r; + end + property rec_getter read frect_getter write frect_getter; //ÇøÓò»ñÈ¡ + property fresh_caller read ffresh_caller write ffresh_caller; //ˢлص÷ private function get_axes_idx(axs); begin @@ -120,510 +315,13 @@ type tcustomfigure = class(tcustomcontrol,tg_const) // return -1; end private + [weakref] frect_getter; + [weakref] ffresh_caller; fwilladdaxs; fwilldelaxs; - faxeses; + faxeses; end -type tg_axis_main = class(tg_axis) //Ö÷Öá - public - function create(pms); - begin - inherited; - end - protected - function get_axes();override; - begin - return faxes; - end - function set_axes(axs);override; - begin - faxes := axs; - end - private - [weakref] faxes; -end -type tg_label_axes = class(tg_label) //×ø±êϵ±êÇ© - public - function create(pms); - begin - inherited; - auto_position := tgc_on; - end - protected - function get_axes();override; - begin - return faxes; - end - function set_axes(axs);override; - begin - faxes := axs; - end - private - [weakref] faxes; -end -type tg_axis = class(tg_base) //Öá¶ÔÏó - function create(pms); - begin - inherited; - fticksize := 12; - fsubticksize := 6; - ftics_direction := tgc_bottom; // - fxtics_coord := array(0,1,2,3); - ftcmin := 0; - ftcmax := 3; - ftccount := 3; - fxtics_coord_v := array(0,1,2,3); - fytics_coord := 0; - ftics_labels := array("0","1","2","3"); - ftics_segment := tgc_on; - ftics_style := tgc_t_s_v;//"v"; - fsub_tics := 2; - ftics_color := nil; - //"v". It's the default value, In this case, tics positions are given by the row factor xtics_coord for horizontal axis (ytics_coord for the vertical one). - //"r". In this case, tics positions are given by the vector [min,max,n] where n is the number of intervals. - //"i". In this case the vector given tics positions is of size 4, [k1,k2,a,n] then values are increasing between k1*10^a and k2*10^a, n is the number of intervals. - end - function executecommand(cmd,pm);virtual; - begin - case cmd of - "get_tics_value":return fxtics_coord_v; - - end; - end - function paint(cvs);override; - begin - if not visible then return ; - subtks := array(); - idx := 0; - if fsub_tics>1 then - begin - for i:= 0 to length(fxtics_coord_v)-2 do - begin - dx := (fxtics_coord_v[i+1]-fxtics_coord_v[i])/fsub_tics; - for j := 1 to (fsub_tics-1) do - begin - subtks[idx++] := fxtics_coord_v[i]+dx*j; - end - end - end - case ftics_direction of - tgc_top: - begin - draw_axis(cvs,subtks,1); - end - tgc_bottom: - begin - draw_axis(cvs,subtks,1+2); - end - tgc_left: - begin - draw_axis(cvs,subtks,0); - end - tgc_right: - begin - draw_axis(cvs,subtks,0+2); - end - - end - end - protected - function check_parent(p);override; - begin - return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes)); - end - published - ///////////////////////////////////// - property tics_direction read ftics_direction write set_tics_direction;//= "top" - property xtics_coord read fxtics_coord write set_xtics_coord ;//= [2,3,4,5,6,7] - property ytics_coord read fytics_coord write set_ytics_coord ;//= 4 - property tics_segment read ftics_segment write set_tics_segment; // true,false - property tics_color read ftics_color write set_tics_color; // -1 - property tics_style read ftics_style write set_tics_style; // = "v" - property sub_tics read fsub_tics write set_sub_tics; // = 2 - property tics_labels read ftics_labels write set_tics_labels; // = ["2","3","4","5","6","7"] - private - fticksize; - fsubticksize; - fxtics_coord_v; - ftcmin; - ftcmax; - ftccount; - /////////////////////////////// - ftics_direction; - fxtics_coord; - fytics_coord; - fsub_tics; - ftics_color; - ftics_segment; - ftics_style; - ftics_labels; - //format_n ;//= "" - //fractional_font ;//= "off" - //clip_state ;//= "off" - //clip_box ;//= [] - //user_data ;//= [] - //tag ;//= "" - private - function draw_axis(cvs,subtks,flg); - begin - tklen := fticksize; - tklensub := fsubticksize; - vtic := flg .& 1 ; - vtic2 := (flg .&2)?1:-1; - - cvs.pen.width := lineinfo.width; - cvs.pen.color := lineinfo.color; - cvs.pen.style := lineinfo.style; - - cvs.font.color := fontinfo.color; - cvs.font.bkcolor := fontinfo.bkcolor; - cvs.font.width := fontinfo.size; - cvs.font.height := fontinfo.size*2; - - if ftics_segment=tgc_on then - begin - for i,v in fxtics_coord_v do - begin - if vtic then - Coordinate_Mapping(v,fytics_coord,0,x,y); - else Coordinate_Mapping(fytics_coord,v,0,x,y); - if i=0 then - cvs.moveto(array(x,y)); - else - cvs.lineto(array(x,y)); - end - end - if ifnumber(ftics_color) then cvs.pen.color := ftics_color; - for i,v in fxtics_coord_v do - begin - if vtic then - Coordinate_Mapping(v,fytics_coord,0,x,y); - else Coordinate_Mapping(fytics_coord,v,0,x,y); - lbi := ftics_labels[i]; - cvs.moveto(array(x,y)); - sz := nil; - if lbi then - begin - sz := array((length(lbi))*fontinfo.size+4,fontinfo.size*2+4) ;//cvs.GetTextExtent(lbi); - end - if vtic then - begin - ny := y+(vtic2*tklen); - cvs.lineto(array(x,ny)); - if sz then - begin - rec := array(x-sz[0]/2,0,x+sz[0]/2,0); - if ny>y then - begin - rec[1] := ny+5; - rec[3] := ny+sz[1]+5; - - end else - begin - rec[1] := ny-sz[1]-5; - rec[3] := ny-5; - end - end - cvs.drawtext(lbi,rec); - end - else - begin - nx := x+(vtic2*tklen); - cvs.lineto(array(nx,y)); - if sz then - begin - rec := array(0,y-sz[1]/2,0,y+sz[1]/2); - if nx>x then - begin - rec[0] := nx+5; - rec[2] := nx+sz[0]+5; - end else - begin - rec[0] := nx-sz[0]-5; - rec[2] := nx-5; - end - cvs.drawtext(lbi,rec); - end - - end - //cvs.textout(lbi,array(x,y)); - end - - for i,v in subtks do - begin - if vtic then - Coordinate_Mapping(v,fytics_coord,0,x,y); - else Coordinate_Mapping(fytics_coord,v,0,x,y); - cvs.moveto(array(x,y)); - if vtic then - cvs.lineto(array(x,y+(vtic2*tklensub))); - else - cvs.lineto(array(x+(vtic2*tklensub),y)); - end - end - function set_tics_direction(v); - begin - if v<>ftics_direction and ( v in array(tgc_top,tgc_left,tgc_right,tgc_bottom)) then - begin - ftics_direction := v; - prop_changed("tics_direction",v); - end - end - function tc_to_label(v); - begin - return format("%.2f",v);//tostn(v); - end - function set_xtics_coord(v); - begin - if v<> fxtics_coord and ifarray(v) then - begin - case ftics_style of - tgc_t_s_v: - begin - lbs := array(); - for i,vi in v do - begin - if not ifnumber(vi) then return ; - lbs[i] := tc_to_label(v); - end - ftcmin := minvalue(v); - ftcmax := maxvalue(v); - if ftcmin=ftcmax then return ; - ftccount := length(v)-1; - fxtics_coord := v; - fxtics_coord_v := v; - ftics_labels := lbs; - end - tgc_t_s_r: - begin - if not(v[0]=1) then return ; - fxtics_coord := v; - ftcmin := v[0]; - ftcmax :=v[1]; - ftccount := v[2]; - type_c_to_r(); - end - - end; - fxtics_coord := v; - prop_changed("xtics_coord",v); - end - end - function set_ytics_coord(v); - begin - if v<> fytics_coord then - begin - fytics_coord := v; - prop_changed("ytics_coord",v); - end - end - function set_tics_segment(v); - begin - nv := v?true:false; - if ftics_segment<>v then - begin - ftics_segment := v; - prop_changed("tics_segment",v); - end - end - function set_tics_color(v); - begin - nv := v?true:false; - if ftics_color<>v then - begin - ftics_color := v; - prop_changed("tics_color",v); - end - end - function set_tics_style(v); - begin - if v<>ftics_style and( v in array(tgc_t_s_v,tgc_t_s_r)) then - begin - ftics_style := v; - case v of - tgc_t_s_v: - begin - fxtics_coord := array(); - for i,v in fxtics_coord_v do - begin - fxtics_coord[i] := v; - end - end - tgc_t_s_r: - begin - fxtics_coord := array(); - fxtics_coord[0] := ftcmin; - fxtics_coord[1] := ftcmax; - fxtics_coord[2] := ftccount; - type_c_to_r(); - end - end ; - prop_changed("tics_style",v); - end - end - function type_c_to_r(); - begin - fxtics_coord_v := array(); - ftics_labels := array(); - vidx := 0; - for x := ftcmin to ftcmax step (ftcmax-ftcmin)/ftccount do - begin - fxtics_coord_v[vidx] := x; - ftics_labels[vidx] := tc_to_label(x); - vidx++; - end - if x>=ftcmax then - begin - fxtics_coord_v[vidx-1] := ftcmax ; - ftics_labels[vidx-1] := tc_to_label(ftcmax) ; - - end else - begin - fxtics_coord_v[vidx] := ftcmax ; - ftics_labels[vidx] := tc_to_label(ftcmax) ; - end - - end - function set_sub_tics(v); - begin - if v>=0 and v<>fsub_tics then - begin - fsub_tics := v; - prop_changed("sub_tics",v); - end - end - function set_tics_labels(v); - begin - if ifarray(v) and v<>ftics_labels then - begin - ftics_labels:=v; - prop_changed("tics_labels",v); - end - end -end - -type tg_label =class(tg_base) //±êÇ©¶ÔÏó - function create(pms); - begin - inherited; - ftext := false; - fposition := array(0,0); - fauto_position_value := array(0,0); - ffill_mode := false; - ffont_angle := 0; - fauto_position := tgc_off; - fauto_rotation := false; - end - function paint(cvs);override; - begin - if not visible then return ; - if not ftext then return ; - cvs.font.width := fontinfo.size; - cvs.font.height := fontinfo.size*2; - cvs.font.color := fontinfo.color; - if fauto_position=tgc_on then - begin - p := fauto_position_value; - end else - begin - p := fposition; - end - if Coordinate_Mapping(p[0],p[1],0,x_,y_) then - begin - if ffont_angle<>0 then - begin - cvs.SaveDC(); - cvs.trans(ffont_angle,x_,y_); - cvs.textout(ftext,array(0,0)); - cvs.RestoreDC(); - end else - cvs.textout(ftext,array(x_,y_)); - end - end - protected - function check_parent(p);override; - begin - return (not p) or (p is class(tg_axis)); - end - published - property text read ftext write set_text;//= "" - property position read fposition write set_positon;//[-27.697388,-1.7130177] - property auto_position read fauto_position write set_auto_position;//"on" - property auto_postion_value read fauto_position_value write fauto_position_value;//"on" - property auto_rotation read fauto_rotation write set_auto_rotation;//"on" - property font_angle read ffont_angle write set_font_angle;//90 - //font_foreground ;//= 6 - //foreground ;//= 9 - //background ;//= 23 - //fill_mode ;//= "off" - //font_style ;//= 6 - //font_size ;//= 4 - //fractional_font ;//= "off" - //font_angle ;//= 90 - private - ftext; - fposition; - fauto_position_value; - ffont_angle; - fauto_position; - fauto_rotation; - private - function set_auto_position(v); - begin - if not(tgc_off=v or tgc_on=v) then return ; - if v<>fauto_position then - begin - fauto_position := v; - prop_changed("auto_postion",nil); - end - end - function set_font_angle(v); - begin - if v<>ffont_angle and ifnumber(v) then - begin - ffont_angle := v; - prop_changed("font_angle",v); - end - end - function set_text(v); - begin - if ifstring(v) and v<>ftext then - begin - ftext := v; - prop_changed("text",nil); - end - end - function set_positon(v); - begin - if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) and v[0]<>fposition[0] and v[1]<>fposition[1] then - begin - fposition[0] :=v[0]; - fposition[1] :=v[1]; - fauto_position := tgc_off; - prop_changed("postion",v); - end - end - function set_auto_rotation(v); - begin - if fauto_rotation<>v and (v in array(tgc_on,tgc_off)) then - begin - fauto_rotation := v; - prop_changed("auto_rotation",v); - end - end -end -type tg_compound = class(tg_graph) //×éºÏ¶ÔÏó - function create(pms); - begin - inherited; - end - protected - function check_parent(p);override; - begin - return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes)); - end -end -type tg_axes = class(tg_graph) //×ø±êϵ +type tg_axes = class(tg_base) //×ø±êϵ private [weakref]fFigure; ///////////////×ø±ê¸¨Öú¼ÆËã///////////////////////// @@ -639,56 +337,141 @@ type tg_axes = class(tg_graph) // dy_len; rt_x; rt_y; + f_changed; + static const c_g_paint_rect=2; + static const c_g_data_changed=1; + static const c_g_data_zoombox=4; /////////////////////////////////////////// public + function executecommand(cmd,pm);override; + begin + ochanged := f_changed; + case cmd of + "zoom_inc": + begin + if not ifarray(pm) then return ; + p := pm["pos"]; + flg := false; + for i := 0 to 1 do + begin + a0 := fzoom_box[i,0]; + b0 := fzoom_box[i,1]; + if not xy_in_paint_rect(p[0],p[1]) then + begin + continue; + end + if not Coordinate_unMapping(p[0],p[1],x,y,z) then continue ; + dx := ((pm["delta"]>0)?(1.05):(1/1.05)); + if not zoom_bound_op(a0,b0,dx,array(x,y)[i],a,b) then continue ; + rt := 1; + cg := 0; + if afdata_bounds[i,1]*rt then + begin + cg++; + b := fdata_bounds[i,1]*rt; + end + if cg=2 then continue; + fzoom_box[i] := array(a,b); + f_changed .|= c_g_data_zoombox; + flg := true; + end + if flg then prop_changed("Coordinate",f_changed); + return flg; + end + "node_add_in": + begin + if pm is class(tg_graph_base) then + begin + f_changed .|= c_g_data_changed; + f_changed .|= c_g_data_zoombox; + end + end + "figure_changed": + begin + f_changed .|= c_g_paint_rect; + f_changed .|= c_g_data_zoombox; + end + "data_changed": + begin + f_changed .|= c_g_data_changed; + f_changed .|= c_g_data_zoombox; + end + + end ; + if ochanged<>f_changed then prop_changed("data_changed",f_changed); + end function Coordinate_unMapping(x,y,_x,_y,_z);override; //»­²¼µ½×ø±ê begin - if not(fFigure and fFigure.HandleAllocated()) then return 0; + if not(fFigure) then return 0; if faxes_reverse[0]=tgc_on then //xÖá begin - _x := fdata_bounds[0,0]-(x-p_left-p_width)/rt_x; + _x := fzoom_box[0,0]-(x-p_left-p_width)/rt_x; end else begin - _x := (x-p_left)/rt_x+fdata_bounds[0,0]; + _x := (x-p_left)/rt_x+fzoom_box[0,0]; end if faxes_reverse[1]=tgc_on then //yÖá begin - _y := (y-p_top)/rt_y +fdata_bounds[1,0]; + _y := (y-p_top)/rt_y +fzoom_box[1,0]; end else begin - _y := fdata_bounds[1,0]-(y-p_top-p_height)/rt_y; + _y := fzoom_box[1,0]-(y-p_top-p_height)/rt_y; end return true; end + function axes_mapping(x,y,z,_x,_y);override;//×ø±êϵÏà¶ÔλÖõ½»­²¼ + begin + if not(fFigure ) then return 0; + _x := p_left+p_width*x ; + _y := p_top +p_height*y; + return true; + end + function axes_unmapping(x,y,_x,_y,_z);override;//»­²¼Î»Öõ½×ø±êϵÏà¶ÔλÖà + begin + if not(fFigure ) then return 0; + _x := (x-p_left)/p_width; + _y := (y-p_top)/p_height; + return true; + end function Coordinate_Mapping(x,y,z,_x,_y);override; //×ø±êµ½»­²¼ begin - if not(fFigure and fFigure.HandleAllocated()) then return 0; + if not(fFigure) then return 0; if faxes_reverse[0]=tgc_on then //xÖá begin - _x := p_left+p_width-(x-fdata_bounds[0,0])*rt_x; + _x := p_left+p_width-(x-fzoom_box[0,0])*rt_x; end else begin - _x := (x-fdata_bounds[0,0])*rt_x+p_left; + _x := (x-fzoom_box[0,0])*rt_x+p_left; end if faxes_reverse[1]=tgc_on then //yÖá begin - _y := (y-fdata_bounds[1,0])*rt_y+p_top; + _y := (y-fzoom_box[1,0])*rt_y+p_top; end else begin - _y := p_top+p_height-(y-fdata_bounds[1,0])*rt_y; + _y := p_top+p_height-(y-fzoom_box[1,0])*rt_y; end return true; end - function paint(cvs);override; + function paint_pre(cvs); begin if not visible then return ; + axes_changed(); modify_coordinate_postion(); r := array(p_left-1,p_top-1,p_left+p_width+1,p_top+p_height+1); - o := new TCanvsRgnClipAutoSave(cvs,r); + cvs.axesrec := r; + paint(cvs); + cvs.axesunclip(); + end + function paint(cvs);override; + begin + paint_grid(cvs); inherited; - o := nil; - paint_grid(cvs); - + cvs.axesunclip(); for i,v in faxes_objects do //»æÖÆ×ø±ê begin v.paint(cvs); @@ -700,6 +483,7 @@ type tg_axes = class(tg_graph) // end if fbox = tgc_on then begin + set_lineinfo_to_canvas(cvs); cvs.moveto(array(p_left,p_top)); cvs.lineto(array(p_left+p_width,p_top)); cvs.lineto(array(p_left+p_width,p_top+p_height)); @@ -707,46 +491,59 @@ type tg_axes = class(tg_graph) // cvs.lineto(array(p_left,p_top)); end end - - function axes_paint_rect_changd(); //»æÖÆÇøÓò¸Ä±ä + function axes_changed();//¸Ä±ä begin - fr := fFigure.clientrect; - w := fr[2]-fr[0]; - h := fr[3]-fr[1]; - p_left := fr[0]+w*fmargins[0]+faxes_bounds[0]; - p_top := fr[1]+h*fmargins[1]+faxes_bounds[1]; - p_width := w*(1-fmargins[0]-fmargins[2])*faxes_bounds[2]; - p_height := h*(1-fmargins[1]-fmargins[3])*faxes_bounds[3]; - merge_graph_data_bounds(); - axes_data_bounds_changed(); + if not fFigure then return ; + if f_changed then + begin + fr := fFigure.rect(); + w := fr[2]-fr[0]; + h := fr[3]-fr[1]; + p_left := fr[0]+w*fmargins[0]+faxes_bounds[0]; + p_top := fr[1]+h*fmargins[1]+faxes_bounds[1]; + p_width := w*(1-fmargins[0]-fmargins[2])*faxes_bounds[2]; + p_height := h*(1-fmargins[1]-fmargins[3])*faxes_bounds[3]; + if (f_changed .& c_g_data_changed)=c_g_data_changed then + begin + tbds := fdata_bounds; + for i,v in get_node_data_bounds(self(true)) do + begin + if not fdata_bounds_locked[i] then + begin + new_bounds(v[0],v[1],a_,b_); + tbds[i] := array(a_,b_);//v*1.05; + end + end + fdata_bounds := tbds; + fzoom_box := tbds; + end + if (f_changed .& c_g_data_zoombox)=c_g_data_zoombox then + begin + auto_set_axis(); + end + dx_min := fzoom_box[0,0]; + dx_max := fzoom_box[0,1]; + dx_len := dx_max-dx_min; + dy_min := fzoom_box[1,0]; + dy_max := fzoom_box[1,1]; + dy_len := dy_max-dy_min; + rt_x := p_width/ dx_len; + rt_y := p_height/dy_len; + end + f_changed := 0; end - function axes_data_bounds_changed(); //Êý¾ÝÇøÓò - begin - dx_min := fdata_bounds[0,0]; - dx_max := fdata_bounds[0,1]; - dx_len := dx_max-dx_min; - dy_min := fdata_bounds[1,0]; - dy_max := fdata_bounds[1,1]; - dy_len := dy_max-dy_min; - rt_x := p_width/ dx_len; - rt_y := p_height/dy_len; - end - function merge_graph_data_bounds();//Êý¾ÝÇøÓò - begin - d := get_data_bounds(); - fdata_bounds := d; - faxes_objects[0].xtics_coord := array(d[0,0],d[0,1],10); - faxes_objects[1].xtics_coord := array(d[1,0],d[1,1],10); - end + function create(pms); begin inherited; + fdata_bounds_locked := array(0,0,0); + f_changed := 0; fgrid := array(); for i:= 0 to 1 do begin gd := new tg_line_info(); gd.width := 0; - gd.Style := tgc_PS_DASH; + gd.Style := tgc_PS_DOT; fgrid[i] := gd; end faxes_reverse := array(tgc_off,tgc_off,tgc_off); @@ -759,7 +556,7 @@ type tg_axes = class(tg_graph) // for i := 0 to 2 do begin axi := new tg_axis_main(); - axi.tics_style := tgc_t_s_r; + axi.tics_style := tgc_tics_v;//tgc_tics_r; case i of 0: axi.tics_direction := tgc_bottom; 1:axi.tics_direction := tgc_left; @@ -778,11 +575,11 @@ type tg_axes = class(tg_graph) // fy_label.font_angle := pi()/2; - fauto_ticks := array("on","on","on"); + fauto_ticks := array(tgc_on,tgc_on,tgc_on); fmargins := array(0.125,0.125,0.125,0.125); faxes_bounds := array( 0,0,1,1); fdata_bounds := array((0,1),(0,1),(0,1)); - fzoom_box := array(); + fzoom_box := fdata_bounds; //FA vector containing the handles of all graphics objects children of the //axes These graphics objects are of type //"Compound", "Rectangle", "Polyline", "Segs", "Arc", "Grayplot",.. (see Compound_properties, @@ -808,12 +605,13 @@ type tg_axes = class(tg_graph) // property margins read gs_margins write gs_margins; property axes_bounds read gs_axes_bounds write gs_axes_bounds; property data_bounds read gs_data_bounds write gs_data_bounds; - property zoom_box read fzoom_box write fzoom_box; + property zoom_box read gs_zoom_box write gs_zoom_box; //ÔÚ´°¿ÚÖеÄÇøÓò //Íø¸ñÏß property grid read get_grid; + //grid ;//= [-1,-1] //grid_position ;//= "background" //grid_thickness ;//= [1,1] @@ -871,6 +669,7 @@ type tg_axes = class(tg_graph) // fmargins; faxes_bounds ;//= [0,0,1,1] fdata_bounds; + fdata_bounds_locked; ffilled; fauto_ticks; ftitle; @@ -890,137 +689,200 @@ type tg_axes = class(tg_graph) // xg := fgrid[0]; if xg.width>0 and ifnumber(xg.color) then begin - cvs.pen.width :=xg.width; - cvs.pen.color := xg.color; - cvs.pen.Style := xg.Style; + set_lineinfo_to_canvas(cvs,xg); y1 := p_top; y2 := p_top+p_height; for i,v in faxes_objects[0].executecommand("get_tics_value") do begin + if vfzoom_box[0,1] then continue; if Coordinate_Mapping(v,0,0,_x,_y) then begin cvs.moveto(array(_x,y1)); cvs.lineto(array(_x,y2)); - end - + end end end xg := fgrid[1]; if xg.width>0 and ifnumber(xg.color) then begin - cvs.pen.width :=xg.width; - cvs.pen.color := xg.color; - cvs.pen.Style := xg.Style; + set_lineinfo_to_canvas(cvs,xg); x1 := p_left; x2 := p_left+p_width; for i,v in faxes_objects[1].executecommand("get_tics_value") do begin + if vfzoom_box[1,1] then continue; if Coordinate_Mapping(0,v,0,_x,_y) then begin cvs.moveto(array(x1,_y)); cvs.lineto(array(x2,_y)); - end - + end end - end - - - end - function get_tics(tk); - begin - r := array(); - rd := tk.xtics_coord; - case tk.tics_style of - tgc_t_s_v: - begin - - end - else //tgc_t_s_r: - begin - - end end end + function auto_set_axis();//×Ô¶¯¼ÆËã×ø±ê + begin + sz := array(p_width,p_height); + for i:=0 to 1 do + begin + axi :=faxes_objects[i]; + axi.executecommand("set_bounds",fzoom_box[i]); + fsz := axi.fontinfo.size; + if fauto_ticks[i] = tgc_on then + begin + if i=0 then + begin + n := integer(sz[0]/(fsz*15)); + end else + if i=1 then + begin + n := integer(sz[1]/(fsz*6)); + end + xcd := array(); + xcdls := array(); + if n>0 then + begin + rt := new_bounds(fzoom_box[i,0],fzoom_box[i,1],a_,b_); + bs :=ceil((b_-a_)/(rt)/n); + axi.sub_tics := bs; + stp := bs*rt; + vi := a_; + ii := 0; + while vi<=b_ do + begin + xcd[ii++] := vi; + vi+=stp; + end + end + axi.xtics_coord := xcd; + end + end + end + function xy_in_paint_rect(x,y);//Êó±êÊÇ·ñÔÚ×ø±êÄÚ + begin + if not ifnumber(x) then return false; + if not ifnumber(y) then return false; + if x(p_left+p_width) then return false; + if y(p_top+p_height) then return false; + return true; + end + function zoom_bound_op(a,b,dx,x,a1,b1);//Ëõ·Å + begin + if xb then return false; + if not(ifnumber(dx)) then return false ; + len := (b-a)/dx; + rt := (x-a)/(b-a); + a1 := x-len*rt; + b1 := a1+len; + return true; + end function modify_label_postion(); //ÐÞÕý±êǩλÖà begin - if fx_label and fx_label.visible and fx_label.text then + if fx_label and (fx_label.visible=tgc_on) and (fx_label.auto_position=tgc_on) then begin s := fx_label.text; if s then begin x := p_left+(p_width-length(s)*10)/2; - Coordinate_unMapping(x,p_top+p_height+40,_x,_y,_z); + ax := faxes_objects[0]; + y := p_top+p_height+20; + if ax.visible=tgc_on and ax.tics_direction = tgc_bottom then + begin + y +=ax.fontinfo.size*2; + end + Coordinate_unMapping(x,y,_x,_y,_z); p := array(_x,_y); fx_label.auto_postion_value := p; end end - if fy_label and fy_label.visible and fy_label.text then + if fy_label and (fy_label.visible=tgc_on) and (fy_label.auto_position=tgc_on) then begin s := fy_label.text; if s then begin y := p_top+(p_height-length(s)*10)/2; - if (fy_location= tgc_left) then x := p_left+p_width+40; - else - x := p_left-40; + if (fy_location= tgc_left) then + begin + x := p_left+p_width+5; + end + else + begin + x := p_left-5; + end Coordinate_unMapping(x,y,_x,_y,_z); p := array(_x,_y); fy_label.auto_postion_value := p; end end - if ftitle and ftitle.visible then + if ftitle and (ftitle.visible=tgc_on) and (ftitle.auto_position=tgc_on) then begin s := ftitle.text; if s then begin + ax := faxes_objects[0]; + y := p_top-20-(ftitle.fontinfo.size*2); + if (ax.visible=tgc_on) and (ax.tics_direction = tgc_top) then + begin + y -=(ax.fontinfo.size*2); + end x := p_left+(p_width-length(s)*10)/2; - Coordinate_unMapping(x,p_top-40,_x,_y,_z); - p := array(_x,_y); - ftitle.auto_postion_value := p; + Coordinate_unMapping(x,y,_x,_y,_z); + ftitle.auto_postion_value := array(_x,_y);; end end end - function modify_coordinate_postion(); + function modify_coordinate_postion();//ÐÞÕý×ø±êÖáλÖà begin + axy := faxes_objects[1]; case fy_location of tgc_left: begin - faxes_objects[1].ytics_coord := fdata_bounds[0,(faxes_reverse[0] = tgc_on)]; + axy.ytics_coord := fzoom_box[0,(faxes_reverse[0] = tgc_on)]; end tgc_right: begin - faxes_objects[1].ytics_coord := fdata_bounds[0,(faxes_reverse[0]<> tgc_on)]; + axy.ytics_coord := fzoom_box[0,(faxes_reverse[0]<> tgc_on)]; end tgc_middle: begin - faxes_objects[1].ytics_coord := fdata_bounds[0,0]+(fdata_bounds[0,1]-fdata_bounds[0,0])/2; + axy.ytics_coord := fzoom_box[0,0]+(fzoom_box[0,1]-fzoom_box[0,0])/2; end tgc_origin: begin - faxes_objects[1].ytics_coord := 0; + if fzoom_box[0,0]<0 and fzoom_box[0,1]>0 then + axy.ytics_coord := 0; + else + begin + axy.ytics_coord := fzoom_box[0,(faxes_reverse[0] = tgc_on)]; + end end end ; + axx := faxes_objects[0]; case fx_location of tgc_bottom: begin - faxes_objects[0].ytics_coord := fdata_bounds[1,(faxes_reverse[1]= tgc_on)]; + axx.ytics_coord := fzoom_box[1,(faxes_reverse[1]= tgc_on)]; end tgc_top: begin - faxes_objects[0].ytics_coord := fdata_bounds[1,(faxes_reverse[1]<> tgc_on)]; + axx.ytics_coord := fzoom_box[1,(faxes_reverse[1]<> tgc_on)]; end tgc_middle: begin - faxes_objects[0].ytics_coord := fdata_bounds[1,0]+(fdata_bounds[1,1]-fdata_bounds[1,0])/2; + axx.ytics_coord := fzoom_box[1,0]+(fzoom_box[1,1]-fzoom_box[1,0])/2; end tgc_origin: begin - faxes_objects[0].ytics_coord := 0; + if fzoom_box[1,0]<0 and fzoom_box[1,1]>0 then + axx.ytics_coord := 0; + else + begin + axx.ytics_coord := fzoom_box[1,(faxes_reverse[1]= tgc_on)]; + end end end ; end - function SetFigure(v); + function SetFigure(v); //Ìí¼Ó´°¿Ú begin if v=fFigure then return ; if fwilladdfigure and fwilladdfigure=v then @@ -1028,6 +890,7 @@ type tg_axes = class(tg_graph) // fwilladdfigure := nil; fFigure := v; v.add_axes(self(true)); + f_changed .|= c_g_paint_rect; return ; end if fwilldelfigure and fwilldelfigure=tp then @@ -1044,7 +907,7 @@ type tg_axes = class(tg_graph) // tp.del_axes(self(true)); fwilldelfigure := nil; end - if v is class(tcustomfigure) then //Ìí¼Ó + if v is class(tg_figure) then //Ìí¼Ó begin fwilladdfigure := v; v.add_axes(self(true)); @@ -1056,15 +919,16 @@ type tg_axes = class(tg_graph) // end function set_filled(v); begin - if (v in array(tgc_on,tgc_off)) and v<>fbox then + if not tg_boolen_value(v,nv) then return ; + if nv<>fbox then begin - ffilled := v; - prop_changed("ffilled",v); + ffilled := nv; + prop_changed("ffilled",nv); end end function set_box(v); begin - if (v in array(tgc_box_on,tgc_box_on,tgc_box_half,tgc_box_hidden_axes)) and v<>fbox then + if (v in array(tgc_box_on,tgc_box_off,tgc_box_half,tgc_box_hidden_axes)) and v<>fbox then begin fbox := v; prop_changed("box",v); @@ -1085,7 +949,7 @@ type tg_axes = class(tg_graph) // begin fy_location := v; if v=tgc_left or v=tgc_right then faxes_objects[1].tics_direction := v; - prop_changed("x_location",v); + prop_changed("y_location",v); end end function get_grid(idx); @@ -1096,15 +960,18 @@ type tg_axes = class(tg_graph) // begin return ; end - function gs_auto_ticks(idx,v); + function gs_auto_ticks(idx,v);//×Ô¶¯¸üÐÂ×ø±ê±êÇ© begin - if v=tgc_on or v=tgc_off then + tg_boolen_value(v,nv); + if nv=tgc_on or nv=tgc_off then begin if idx in array(0,1,2) then begin - if fauto_ticks[idx]<>v then + if fauto_ticks[idx]<>nv then begin - fauto_ticks[idx] := v; + fauto_ticks[idx] := nv; + if nv=tgc_on then faxes_objects[i].tics_style := tgc_tics_v;//faxes_objects[i].tics_style := tgc_tics_r; + //else faxes_objects[i].tics_style := tgc_tics_v; prop_changed("auto_ticks",idx); end end @@ -1127,7 +994,8 @@ type tg_axes = class(tg_graph) // begin if idx in array(0,1,2,3) then begin - faxes_bounds[idx] := array(v[0],v[1]); + faxes_bounds[idx] := array(v[0],v[1]); + f_changed .|=c_g_paint_rect ; prop_changed("axes_bounds",idx); end end else //get @@ -1138,11 +1006,19 @@ type tg_axes = class(tg_graph) // end function gs_data_bounds(idx,v); begin + if v=-1 then + begin + if idx in array(0,1,2) then + begin + fdata_bounds_locked[idx] := false; + end + end else if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then begin if idx in array(0,1,2) then begin fdata_bounds[idx] := v; + fdata_bounds_locked[idx] := true; prop_changed("data_bounds",idx); end end else //get @@ -1151,8 +1027,22 @@ type tg_axes = class(tg_graph) // return fdata_bounds; end end - - function gs_axes_reverse(idx,v); + function gs_zoom_box(idx,v); + begin + if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then + begin + if idx in array(0,1,2) then + begin + fzoom_box[idx] := v; + prop_changed("zoom_box",idx); + end + end else //get + begin + if idx in array(0,1,2) then return fzoom_box[idx]; + return fzoom_box; + end + end + function gs_axes_reverse(idx,v); //·´Ïò begin if v=tgc_off or v=tgc_on then begin @@ -1167,13 +1057,14 @@ type tg_axes = class(tg_graph) // return faxes_reverse; end end - function gs_margins(idx,v); + function gs_margins(idx,v); //¿Õ°× begin if ifnumber(v) then begin if idx in array(0,1,2,3) then begin - fmargins[idx] := v; + fmargins[idx] := v; + f_changed .|= c_g_paint_rect; prop_changed("margins",idx); end end else //get @@ -1182,14 +1073,13 @@ type tg_axes = class(tg_graph) // return fmargins; end end - function gs_sub_ticks(idx,v); + function gs_sub_ticks(idx,v); //С¿Ì¶ÈÏß begin if ifnumber(v) and (v>=0) then begin if idx in array(0,1,2) then begin - faxes_objects[idx].sub_tics := v; - //prop_changed("axes_visible",idx); + faxes_objects[idx].sub_tics := v; end end else //get begin @@ -1197,25 +1087,706 @@ type tg_axes = class(tg_graph) // return array(faxes_objects[0].sub_tics,faxes_objects[1].sub_tics,faxes_objects[2].sub_tics); end end - end -type tg_tips = class(tg_base) +type tg_canvas = class(TcustomCanvas) + uses utslvclgdi; + function create(h); + begin + inherited create(); + FCvsHandle := h; + Handle := h; + faxesrgn := new TRGNRECT(); + end + function axesclip(); + begin + if faxesrgn then + begin + _wapi.SelectClipRgn(FCvsHandle,faxesrgn.Handle); //²Ã¼ôÇøÓò + end + end + function axesunclip(); + begin + _wapi.SelectClipRgn(FCvsHandle,0); + end + function destroy(); + begin + Handle := 0; + faxesrgn := nil; + end + property axesrec read FaxesRec write set_clip_rect; + private + FaxesRec; + FCvsHandle; + faxesrgn; + private + function set_clip_rect(rec); + begin + FaxesRec := rec; + faxesrgn.rect := rec; + end +end +type tg_axis_main = class(tg_axis) //Ö÷Öá + public + function create(pms); + begin + inherited; + end + protected + function SetParent(V);override; + begin + + end + function get_axes();override; + begin + return faxes; + end + function set_axes(axs);override; + begin + if axs is class(tg_axes) then faxes := axs; + end + private + [weakref] faxes; +end +type tg_label_axes = class(tg_label) //×ø±êϵ±êÇ© + public function create(pms); begin inherited; - finterp_mode := tgc_off; - fbox_mode := tgc_on; + auto_position := tgc_on; + end + protected + function SetParent(V);override; + begin + end + function get_axes();override; + begin + return faxes; + end + function set_axes(axs);override; + begin + if axs is class(tg_axes) then faxes := axs; + end + private + [weakref] faxes; +end +type tg_axis = class(tg_base) //Öá¶ÔÏó + function create(pms); + begin + inherited; + fticksize := 12; + fsubticksize := 6; + ftics_direction := tgc_bottom; // + fxtics_coord := array(0,1,2,3); + ftcmin := 0; + ftcmax := 3; + ftccount := 3; + fxtics_coord_v := array(0,1,2,3); + fytics_coord := 0; + ftics_labels := array("0","1","2","3"); + ftics_segment := tgc_on; + ftics_style := tgc_tics_v;//"v"; + fsub_tics := 2; + ftics_color := nil; + //"v". It's the default value, In this case, tics positions are given by the row factor xtics_coord for horizontal axis (ytics_coord for the vertical one). + //"r". In this case, tics positions are given by the vector [min,max,n] where n is the number of intervals. + //"i". In this case the vector given tics positions is of size 4, [k1,k2,a,n] then values are increasing between k1*10^a and k2*10^a, n is the number of intervals. + end + function executecommand(cmd,pm);override; + begin + case cmd of + "get_tics_value":return fxtics_coord_v; + "set_bounds": return set_zoom_bounds(pm); + end; + end + function paint(cvs);override; + begin + if visible<>tgc_on then return ; + subtks := array(); + idx := 0; + if fsub_tics>1 then + begin + for i:= 0 to length(fxtics_coord_v)-2 do + begin + dx := (fxtics_coord_v[i+1]-fxtics_coord_v[i])/fsub_tics; + for j := 1 to (fsub_tics-1) do + begin + vi := fxtics_coord_v[i]+dx*j; + if fzoom_bounds and (vifzoom_bounds[1]) then continue; + subtks[idx++] := vi; + end + end + end + case ftics_direction of + tgc_top: + begin + draw_axis(cvs,subtks,1); + end + tgc_bottom: + begin + draw_axis(cvs,subtks,1+2); + end + tgc_left: + begin + draw_axis(cvs,subtks,0); + end + tgc_right: + begin + draw_axis(cvs,subtks,0+2); + end + end + end + protected + function draw_tics(cvs,info);virtual; + begin + for i,v in info do + begin + cvs.drawtext(v[0],v[1]); + end + end + function check_parent(p);override; + begin + return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes)); + end + published + ///////////////////////////////////// + property tics_direction read ftics_direction write set_tics_direction;//= "top" + property xtics_coord read fxtics_coord write set_xtics_coord ;//= [2,3,4,5,6,7] + property ytics_coord read fytics_coord write set_ytics_coord ;//= 4 + property tics_segment read ftics_segment write set_tics_segment; // true,false + property tics_color read ftics_color write set_tics_color; // -1 + property tics_style read ftics_style write set_tics_style; // = "v" + property sub_tics read fsub_tics write set_sub_tics; // = 2 + property tics_labels read ftics_labels write set_tics_labels; // = ["2","3","4","5","6","7"] + private + fzoom_bounds; + fticksize; + fsubticksize; + fxtics_coord_v; + ftcmin; + ftcmax; + ftccount; + /////////////////////////////// + ftics_direction; + fxtics_coord; + fytics_coord; + fsub_tics; + ftics_color; + ftics_segment; + ftics_style; + ftics_labels; + //format_n ;//= "" + //fractional_font ;//= "off" + //clip_state ;//= "off" + //clip_box ;//= [] + //user_data ;//= [] + //tag ;//= "" + private + function draw_axis(cvs,subtks,flg); + begin + pw := lineinfo.width; + tklen := fticksize+(pw>0?pw:0); + tklensub := fsubticksize+(pw>0?pw:0); + vtic := flg .& 1 ; + vtic2 := (flg .&2)?1:-1; + + set_lineinfo_to_canvas(cvs); + set_fontinfo_to_canvas(cvs); + + ///////////////////ÖáÏß//////////////////////////////// + if ftics_segment=tgc_on then + begin + if fzoom_bounds then + begin + if vtic then + begin + Coordinate_Mapping(fzoom_bounds[0],fytics_coord,0,x,y); + cvs.moveto(array(x,y)); + Coordinate_Mapping(fzoom_bounds[1],fytics_coord,0,x,y); + cvs.lineto(array(x,y)); + end + else + begin + Coordinate_Mapping(fytics_coord,fzoom_bounds[0],0,x,y); + cvs.moveto(array(x,y)); + Coordinate_Mapping(fytics_coord,fzoom_bounds[1],0,x,y); + cvs.lineto(array(x,y)); + end + end else + begin + for i,v in fxtics_coord_v do + begin + if vtic then + Coordinate_Mapping(v,fytics_coord,0,x,y); + else Coordinate_Mapping(fytics_coord,v,0,x,y); + if i=0 then + cvs.moveto(array(x,y)); + else + cvs.lineto(array(x,y)); + end + end + end + ///////////////////////////////////////////////////// + //////////////////¿Ì¶ÈÏßÒÔ¼°¿Ì¶ÈÖµ/////////////////////////////////////// + tcsinfo := array(); + if ifnumber(ftics_color) then cvs.pen.color := ftics_color; + for i,v in fxtics_coord_v do + begin + if fzoom_bounds and (vfzoom_bounds[1]) then continue; + if vtic then + Coordinate_Mapping(v,fytics_coord,0,x,y); + else Coordinate_Mapping(fytics_coord,v,0,x,y); + lbi := ftics_labels[i]; + cvs.moveto(array(x,y)); + sz := nil; + if lbi then + begin + sz := array((length(lbi))*fontinfo.size+4,fontinfo.size*2+4) ;//cvs.GetTextExtent(lbi); + end + if vtic then + begin + ny := y+(vtic2*tklen); + cvs.lineto(array(x,ny)); + if sz then + begin + rec := array(x-sz[0]/2,0,x+sz[0]/2,0); + if ny>y then + begin + rec[1] := ny+5; + rec[3] := ny+sz[1]+5; + end else + begin + rec[1] := ny-sz[1]-5; + rec[3] := ny-5; + end + end + tcsinfo[length(tcsinfo)] := array(lbi,rec,"h"); + //draw_tics(cvs,lbi,rec); + //cvs.drawtext(lbi,rec); + end + else + begin + nx := x+(vtic2*tklen); + cvs.lineto(array(nx,y)); + if sz then + begin + rec := array(0,y-sz[1]/2,0,y+sz[1]/2); + if nx>x then + begin + rec[0] := nx+5; + rec[2] := nx+sz[0]+5; + end else + begin + rec[0] := nx-sz[0]-5; + rec[2] := nx-5; + end + //draw_tics(cvs,lbi,rec); + tcsinfo[length(tcsinfo)] := array(lbi,rec,"v"); + //cvs.drawtext(lbi,rec); + end + + end + //cvs.textout(lbi,array(x,y)); + end + if tcsinfo then draw_tics(cvs,tcsinfo); + ///////////////////////////////////////////////////////////////////////// + ////////////////////×ӿ̶ÈÏß//////////////////////////////////////////////// + for i,v in subtks do + begin + if vtic then + Coordinate_Mapping(v,fytics_coord,0,x,y); + else Coordinate_Mapping(fytics_coord,v,0,x,y); + cvs.moveto(array(x,y)); + if vtic then + cvs.lineto(array(x,y+(vtic2*tklensub))); + else + cvs.lineto(array(x+(vtic2*tklensub),y)); + end + end + function set_zoom_bounds(v); + begin + if ifarray(v) and v[0]ftics_direction and ( v in array(tgc_top,tgc_left,tgc_right,tgc_bottom)) then + begin + ftics_direction := v; + prop_changed("tics_direction",v); + end + end + function tc_to_label(v); + begin + return format("%f",v);//tostn(v); + end + function set_xtics_coord(v); + begin + if v<> fxtics_coord and ifarray(v) then + begin + case ftics_style of + tgc_tics_v: + begin + lbs := array(); + for i,vi in v do + begin + if not ifnumber(vi) then return ; + lbs[i] := tc_to_label(vi); + end + ftcmin := minvalue(v); + ftcmax := maxvalue(v); + if ftcmin=ftcmax then return ; + ftccount := length(v)-1; + fxtics_coord := v; + fxtics_coord_v := v; + ftics_labels := lbs; + end + tgc_tics_r: + begin + if not(v[0]=1) then return ; + fxtics_coord := v; + ftcmin := v[0]; + ftcmax :=v[1]; + ftccount := v[2]; + type_c_to_r(); + end + + end; + fxtics_coord := v; + prop_changed("xtics_coord",v); + end + end + function set_ytics_coord(v); + begin + if v<> fytics_coord then + begin + fytics_coord := v; + prop_changed("ytics_coord",v); + end + end + function set_tics_segment(v); + begin + nv := v?true:false; + if ftics_segment<>v then + begin + ftics_segment := v; + prop_changed("tics_segment",v); + end + end + function set_tics_color(v); + begin + if ftics_color<>v then + begin + ftics_color := v; + prop_changed("tics_color",v); + end + end + function set_tics_style(v); + begin + if v<>ftics_style and( v in array(tgc_tics_v,tgc_tics_r)) then + begin + ftics_style := v; + case v of + tgc_tics_v: + begin + fxtics_coord := array(); + for i,v in fxtics_coord_v do + begin + fxtics_coord[i] := v; + end + end + tgc_tics_r: + begin + fxtics_coord := array(); + fxtics_coord[0] := ftcmin; + fxtics_coord[1] := ftcmax; + fxtics_coord[2] := ftccount; + type_c_to_r(); + end + end ; + prop_changed("tics_style",v); + end + end + function type_c_to_r(); + begin + fxtics_coord_v := array(); + ftics_labels := array(); + vidx := 0; + for x := ftcmin to ftcmax step (ftcmax-ftcmin)/ftccount do + begin + fxtics_coord_v[vidx] := x; + ftics_labels[vidx] := tc_to_label(x); + vidx++; + end + if x>=ftcmax then + begin + fxtics_coord_v[vidx-1] := ftcmax ; + ftics_labels[vidx-1] := tc_to_label(ftcmax) ; + end else + begin + fxtics_coord_v[vidx] := ftcmax ; + ftics_labels[vidx] := tc_to_label(ftcmax) ; + end + + end + function set_sub_tics(v); + begin + if v>=0 and v<>fsub_tics then + begin + fsub_tics := v; + prop_changed("sub_tics",v); + end + end + function set_tics_labels(v); + begin + if ifarray(v) and v<>ftics_labels then + begin + ftics_labels:=v; + prop_changed("tics_labels",v); + end + end +end + +type tg_label =class(tg_base) //±êÇ©¶ÔÏó + function create(pms); + begin + inherited; + ftext := false; + flocation := 0; + fposition := array(0,0); + ffill_mode := false; + ffont_angle := 0; + fauto_rotation := false; + end + function paint(cvs);override; + begin + if tgc_on<>visible then return ; + if not ftext then return ; + set_fontinfo_to_canvas(cvs); + p := fposition; + + if fauto_position=tgc_on then + begin + p := fauto_position_value; + end else + begin + p := fposition; + end + case flocation of + tgc_by_axes: + begin + if not axes_mapping(p[0],p[1],0,x_,y_) then return ; + end else //tgc_by_coordinates: + begin + if not Coordinate_Mapping(p[0],p[1],0,x_,y_) then return ; + end + end + if ffont_angle<>0 then + begin + cvs.SaveDC(); + cvs.trans(ffont_angle,x_,y_); + cvs.textout(ftext,array(0,0)); + cvs.RestoreDC(); + end else + cvs.textout(ftext,array(x_,y_)); + end + protected + function check_parent(p);override; + begin + return (not p) or (p is class(tg_axis)); + end + published + property text read ftext write set_text;//= "" + property position read fposition write set_positon;//[-27.697388,-1.7130177] + property location read flocation write Set_location; + property auto_position read fauto_position write set_auto_position;//"on" + property auto_postion_value read fauto_position_value write fauto_position_value;//"on" + property auto_rotation read fauto_rotation write set_auto_rotation;//"on" + property font_angle read ffont_angle write set_font_angle;//90 + //font_foreground ;//= 6 + //foreground ;//= 9 + //background ;//= 23 + //fill_mode ;//= "off" + //font_style ;//= 6 + //font_size ;//= 4 + //fractional_font ;//= "off" + //font_angle ;//= 90 + private + flocation; + ftext; + fposition; + fauto_position_value; + ffont_angle; + fauto_position; + fauto_rotation; + private + function Set_location(v); + begin + if flocation<>v and (v in array(tgc_by_axes,tgc_by_coordinates)) then + begin + flocation := v; + end + end + function set_auto_position(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fauto_position then + begin + fauto_position := nv; + prop_changed("auto_postion",nil); + end + end + function set_font_angle(v); + begin + if v<>ffont_angle and ifnumber(v) then + begin + ffont_angle := v; + prop_changed("font_angle",v); + end + end + function set_text(v); + begin + if ifstring(v) and v<>ftext then + begin + ftext := v; + prop_changed("text",nil); + end + end + function set_positon(v); + begin + if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) and v[0]<>fposition[0] and v[1]<>fposition[1] then + begin + fposition[0] :=v[0]; + fposition[1] :=v[1]; + fauto_position := tgc_off; + prop_changed("postion",v); + end + end + function set_auto_rotation(v); + begin + if not tg_boolen_value(v,nv) then return ; + if fauto_rotation<>nv then + begin + fauto_rotation := nv; + prop_changed("auto_rotation",nv); + end + end +end +type tg_compound = class(tg_graph) //×éºÏ¶ÔÏó + function create(pms); + begin + inherited; + end + protected + function check_parent(p);override; + begin + return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes)); + end +end + +type tg_tips = class(tg_base) //Ìáʾ + function create(pms); + begin + inherited; + flocation := tgc_by_coordinates; + fdisplay_components := "xy"; + fbox_mode := tgc_on; + fmark_mode := tgc_on; + markinfo.Style := tgc_mks_square; + markinfo.size := 5; fline_style := 0; fforeground := -1; - fbackground := -2; - fmark_mode := tgc_on; + fbackground := -2; fmark_style := 11; + fdata_idx := -1; + frow_mode := false; end - property interp_mode read finterp_mode write finterp_mode; //"on" - property box_mode read fbox_mode write fbox_mode; //"on" + function executecommand(cmd,pm);override; + begin + case cmd of + "fresh": + begin + FData := nil; + ftext :=""; + f_ps := nil; + end + end + end + function paint(cvs);override; + begin + if tgc_on<>visible then return ; + p := parent; + if not p then return ; + d := get_data(); + if ifnil(d) then return ; + ss := get_text(); + if not ss then return ; + if not(f_ps and ifnumber(f_ps[0]) and ifnumber(f_ps[1])) then return ; + ws := 0; + hs := array(); + w := fontinfo.size; + h := w*2; + for i,v in ss do + begin + ws := max(ws,length(v)*w+w); + hs[i] := h+4; + end + Coordinate_Mapping(d[0],d[1],z,x_,y_); + sz := array(ws,sum(hs)); + if fmark_mode = tgc_on then + begin + mk := markinfo; + msz := max(ceil(mk.size/2),2); + paint_marks(mk,cvs,array((x_,y_))); + end + case flocation of + tgc_in_upper_left: lc := 0; + tgc_in_upper_right: lc := 1; + tgc_in_lower_right: lc := 2; + tgc_in_lower_left: lc := 3; + else + lc := (fdata_idx+1) mod 3;//randomfrom(array(0,1,2,3)); + end ; + rec := get_rect_at_corner(x_,y_,sz[0],sz[1],msz,lc); + if fbox_mode=tgc_on then + begin + set_lineinfo_to_canvas(cvs); + cvs.draw_rect.rect(rec).draw(); + end + b_x := rec[0]; + b_y := rec[1]; + set_fontinfo_to_canvas(cvs); + for i,v in ss do + begin + rci := array(b_x,b_y,b_x+ws,b_y+hs[i]); + cvs.drawtext(v,rci); + b_y+=hs[i]; + end + end + published + //property interp_mode read finterp_mode write finterp_mode; //"on" + property location read flocation write set_location; + property box_mode read fbox_mode write set_box_mode; //"on" + property mark_mode read fmark_mode write set_mark_mode; //"on" + property display_components read fdisplay_components write set_display_components; //"xy" + property data_idx read fdata_idx write set_data_idx; + property display_function read fdisplay_function write fdisplay_function; + property texts read get_text write set_text; + property data read get_data; private + [weakref]fdisplay_function; + flocation; fbox_mode; - finterp_mode; + fmark_mode; + //finterp_mode; + fdisplay_components; + fdata_idx; + ftext; + fdata; //auto_orientation ;//= "on" //orientation ;//= 3 //label_mode ;//= "on" @@ -1223,22 +1794,271 @@ type tg_tips = class(tg_base) //display_components ;//= "xy" //display_function ;//= "" //text ;//= ["X:66.064";"Y:-1.351"] - //font_foreground ;//= -1 - //font_style ;//= 6 - //font_size ;//= 1 //detached_position ;//= [] - //mark_size_unit ;//= "point" - //mark_size ;//= 8 - //mark_foreground ;//= -3 - //mark_background ;//= -2 - + protected + function check_parent(p);override; + begin + return ifnil(p) or (p is class(tg_graph)); + end + private + f_ps; + function init_display(tip,ps,txts); + begin + d := get_data(); + if ifarray(d) and ifnumber(d[0]) and ifnumber(d[1]) then + begin + px := d[0]; + py := d[1]; + ps := array(px,py); + txts := array(); + for i := 1 to length(fdisplay_components) do + begin + vi := fdisplay_components[i]; + case vi of + "x","X": + begin + txts[length(txts)] := vi+format(":%f",px); + end + "y","Y": + begin + txts[length(txts)] := vi+format(":%f",py); + end + end ; + end + end + end + function set_text(txt); + begin + if get_text()<>txt and ifarray(txt) then + begin + ftext := array(); + for i,v in txt do + begin + if ifstring(v) then + begin + ftext[idx++] := v; + end + end + end + end + function get_text(); + begin + if ftext then return ftext; + if iffuncptr(display_function) then + begin + call(display_function,self(true),ps,txt); + f_ps := ps; + end else + begin + init_display(self(true),ps,txt); + f_ps := ps; + end + ftext := txt; + return ftext; + end + function get_data(); + begin + if fdata then return FData; + if not(fdata_idx>=0) then return nil; + p := parent; + if p then + begin + FData := p.get_graph_data_by_idx(fdata_idx); + return fdata; + end + return nil; + end + function set_data_idx(idx); + begin + if ifnumber(idx) and idx<>fdata_idx then + begin + fdata_idx := idx ; + executecommand("fresh",pm); + end + end + function set_location(v); + begin + if v<>flocation then + begin + flocation := v; + prop_changed("location",nv); + end + end + function set_display_components(v); + begin + if not( v and ifstring(v)) then return ; + if d_comp_ok(v) and fdisplay_components<>v then + begin + fdisplay_components := v; + executecommand("fresh",pm); + end + end + function set_box_mode(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fbox_mode then + begin + fbox_mode := nv; + prop_changed("box_mode",nv); + end + end + function set_mark_mode(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fmark_mode then + begin + fmark_mode := nv; + prop_changed("mark_mode",nv); + end + end + function d_comp_ok(dcp); + begin + t := array("x":1,"y":1,"z":1); + for i := 1 to length(dcp) do + begin + vi := dcp[i]; + if t[vi]<>1 then return false; + t[vi] := 2; + end + return true; + end end -type tg_legend = class(tg_base) +type tg_legend = class(tg_base) //ͼÀý function create(pms); begin - inherited; + inherited; + fline_mode := tgc_on; + flocation := tgc_in_upper_right; + flinks := array(); + FText := array(); + fposition := nil; end - //parent Axes + function paint(cvs);override; + begin + if tgc_on<>visible then return ; + get_lenged_sizes(lw,lh,ws,hs,objs,ss); + arec := cvs.axesrec; + rc := arec; + dis := 30; + cvs.axesunclip(); + set_lineinfo_to_canvas(cvs); + case flocation of + tgc_upper_caption: + begin + x := arec[0]; + y := arec[1]; + mx := ceil((arec[2]-arec[0]-lw)/2)-dis; + rc := get_rect_at_corner(x,y,lw,lh,dis,2,mx); + cvs.draw_rect().rect(rc).draw(); + end + tgc_lower_caption: + begin + x := arec[0]; + y := arec[3]; + mx := ceil((arec[2]-arec[0]-lw)/2)-dis; + rc := get_rect_at_corner(x,y,lw,lh,dis,1,mx); + cvs.draw_rect().rect(rc).draw(); + end + tgc_in_upper_right: + begin + x := arec[2]; + y := arec[1]; + rc := get_rect_at_corner(x,y,lw,lh,dis,3); + cvs.draw_rect().rect(rc).draw(); + end + tgc_in_upper_left: + begin + x := arec[0]; + y := arec[1]; + rc := get_rect_at_corner(x,y,lw,lh,dis,2); + cvs.draw_rect().rect(rc).draw(); + end + tgc_in_lower_left: + begin + x := arec[0]; + y := arec[3]; + rc := get_rect_at_corner(x,y,lw,lh,dis,1); + cvs.draw_rect().rect(rc).draw(); + end + + tgc_in_lower_right: + begin + x := arec[2]; + y := arec[3]; + rc := get_rect_at_corner(x,y,lw,lh,dis,0); + cvs.draw_rect().rect(rc).draw(); + end + tgc_by_coordinates: //¸ù¾ÝλÖÃÐÅÏ¢ÉèÖô¦Àí + begin + if ifnil(fposition) then + begin + x := arec[2]; + y := arec[1]; + rc := get_rect_at_corner(x,y,lw,lh,0,3); + Coordinate_unMapping(rc[0],rc[1],_x,_y,_z); + fposition := array(_x,_y); + end else + begin + Coordinate_Mapping(fposition[0],fposition[1],0,_x,_y); + rc:= array(_x,_y,_x+lw,_y+lh); + end + cvs.draw_rect().rect(rc).draw(); + end + tgc_by_axes: + begin + if ifnil(fposition) then + begin + x := arec[2]; + y := arec[1]; + rc := get_rect_at_corner(x,y,lw,lh,0,3); + axes_unmapping(rc[0],rc[1],_x,_y,_z); + fposition := array(_x,_y); + end else + begin + axes_mapping(fposition[0],fposition[1],0,_x,_y); + rc:= array(_x,_y,_x+lw,_y+lh); + end + cvs.draw_rect().rect(rc).draw(); + end + end; + b_x := rc[0]; + b_y := rc[1]; + set_fontinfo_to_canvas(cvs); + for i,v in objs do + begin + hi := hs[i]; + if v then + begin + rci := array(b_x,b_y,b_x+ws[0],b_y+hi); + v.paint_legend(cvs,rci); + end + si := ss[i]; + if si then + begin + rci := array(b_x+ws[0],b_y,b_x+ws[0]+ws[1],b_y+hi); + cvs.drawtext(si,rci); + end + b_y+=hi; + end + cvs.axesclip(); + end + published + property location read flocation write set_location; + property postion read fposition write set_postion; + property line_mode read fline_mode write set_line_mode; + property links read flinks write set_links; + property texts read FText write set_text; + protected + function check_parent(p);override; + begin + return ifnil(p) or (p is class(tg_axes)); + end + private + [weakref] flinks; + fline_mode; + flocation; + FText; + fposition; //text ;//= "y1" //font_style ;//= 6 //font_size ;//= 1 @@ -1256,139 +2076,253 @@ type tg_legend = class(tg_base) //marks_count ;//= 3 //clip_state ;//= "off" //clip_box ;//= [] + private + function get_lenged_sizes(lw,lh,ws,hs,objs,ss); + begin + ws := array(0,0); + hs := array(); + w := fontinfo.size; + h := w*2; + objs := array(); + ss := array(); + for i:= 0 to max(length(flinks),length(ftext))-1 do + begin + vi := flinks[i]; + si := ftext[i]; + if vi is class(tg_graph) then + begin + objs[i] := vi; + vi.get_legend_size(w1,h1); + ws[0] := max(ws[0],w1); + end else + begin + h1 := 0; + objs[i] := 0; + end + if ifstring(si) then + begin + ws[1] := max(w*length(si)+2,ws[1]); + ss[i] := si; + end else + begin + ss[i] := nil; + end + hs[i] := max(h+4,h1); + end + lw := ws[0]+ws[1]; + lh := sum(hs); + end + function set_postion(v); + begin + if fposition<>v and ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then + begin + fposition := array(v[0],v[1]); + prop_changed("postion",v); + end + end + function set_text(s); + begin + idx := 0; + flg := false; + for i,v in s do + begin + if not ifstring(v) then continue; + if v<>ftext[idx] then + begin + ftext[idx] := v; + flg++; + end + idx++; + end + if flg then prop_changed("text",s); + end + function set_links(vs); + begin + if ifarray(vs) and vs<>flinks then + begin + flinks := vs; + prop_changed("links_changed",vs); + end + end + function set_location(v); + begin + vs := static array(tgc_in_upper_right,tgc_in_upper_left,tgc_in_lower_right,tgc_in_lower_left, + //tgc_out_upper_right,tgc_out_upper_left,tgc_out_lower_right,tgc_out_lower_left, + tgc_upper_caption,tgc_lower_caption, + tgc_by_coordinates,tgc_by_axes); + if v<>flocation and (v in vs) then + begin + flocation := v; + end + end + function set_line_mode(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fline_mode then + begin + fline_mode := nv; + prop_changed("line_mode",nv); + end + end end -type tg_graph = class(tg_base) - function create(pms); +type tg_graph_base = class(tg_base) //¼æÈÝ»æÍ¼ºÍgoupÁ½¸öÀàÐÍ + function create(pm); begin inherited; end - function get_data_bounds();virtual; + function get_data_bounds();virtual; //»ñÈ¡Êý¾Ý±ß½ç begin - d := zeros(3,2); - for i := 0 to NodeCount-1 do - begin - vi := GetNodeByIndex(i); - if vi is class(tg_graph) then - begin - bds := vi.get_data_bounds(); - mg_bds(bds,d); - end - end - return d; + return get_node_data_bounds(self(true)); end end -type tg_Polyline = class(tg_graph) +type tg_graph = class(tg_graph_base) //»æÍ¼¶ÔÏó,°üÀ¨Êý¾Ý,ÌáʾµÈÄÚÈÝ + function create(pms); + begin + inherited; + fgraph_data := array(); + end + function get_data_tips(); //»ñµÃÊý¾ÝÌáʾ¶ÔÏó + begin + r := array(); + for i:= 0 to NodeCount-1 do + begin + vi := GetNodeByIndex(i); + if vi is class(tg_tips) then + begin + r[ridx++] := vi; + end + end + return r; + end + function get_legend_size(w,h);virtual; + begin + h := fontinfo.size+4; + w := 100; + end + function paint_legend(cvs,rec);virtual; //»æÖÆÍ¼Àý + begin + + end + function get_graph_data_by_idx(idx); //»ñÈ¡Êý¾Ýµã + begin + return fgraph_data[idx]; + end + property graph_data read fgraph_data write set_graph_data; + protected + fgraph_data;//Êý¾Ý + protected + function prop_changed(n,v);override; + begin + case n of + "data": + begin + for i,v in get_data_tips() do + begin + v.executecommand("fresh",nil); + end + ax := axes; + if ax then + ax.executecommand("data_changed"); + end else + begin + inherited; + end + end ; + end + function set_graph_data(v);virtual; + begin + if v<>fgraph_data then + begin + fgraph_data := v; + prop_changed("data",v); + end + end + +end +type tg_Polyline = class(tg_graph) //Ïßͼ¶ÔÏó function create(pms); begin inherited; fclosed := tgc_off; - //fmark_style :=tgc_mks_dot ;//= 9 - //fmark_size_unit := "point";//= "point","tabulated" - //fmark_size :=0;//= 0 - //fmark_foreground := 16;//= 16 - //fmark_background := 15;//= 15 - //fforeground := 33 ;//= 33 - //fbackground := 26 ;//= 26 fline_mode := tgc_on; - fmark_mode := tgc_on; + fmark_mode := tgc_off; fpolyline_style := tgc_LS_interpolated;// interpolated,staircase,barplot,arrowed,filled,bar fbar_width := 0; - fdata_bounds := array((0,10),(0,10),(0,10)); - end + fdata_bounds := array((0,1),(0,1),(0,1)); + end function get_data_bounds();override; begin return fdata_bounds; end function paint(cvs);override; begin - if not visible then return ; - xys := array(); - if fline_mode=tgc_on then + if tgc_on<> visible then return ; + cvs.axesclip(); + xys := array(); + set_lineinfo_to_canvas(cvs); + for i,v in fgraph_data do + begin + if not Coordinate_Mapping(v[0],v[1],z,x,y) then return ; + xys[i] := array(integer(x),integer(y)); + end + Coordinate_Mapping(0,0,0,x,y); + paint_lines(cvs,fpolyline_style,xys,fclosed,array("line_mode":fline_mode,"bar_width":fbar_width,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor,"x":x,"y":y)); + mk := markinfo; + if mark_mode=tgc_on and mk.size>2 then begin - cvs.pen.Style := lineinfo.Style; - cvs.pen.color := lineinfo.color; - cvs.pen.width := lineinfo.width; - for i,v in fdata do - begin - if not Coordinate_Mapping(v[0],v[1],z,x,y) then return ; - xys[i] := array(integer(x),integer(y)); - end - case fpolyline_style of - tgc_LS_staircase: - begin - last := array(); - for i,v in xys do - begin - if i=0 then - begin - last := v; - cvs.moveto(v); - end else - begin - - cvs.lineto(array(v[0],last[1])); - cvs.lineto(v); - last := v; - end - end - end - else - begin - if fclosed and length(xys)>2 then - cvs.draw_polyline().points( xys union xys[0:0]).draw(); - else - cvs.draw_polyline().points(xys).draw(); - end - end; - mk := markinfo; - if mark_mode=tgc_on and mk.size>2 then - begin - paint_marks(mk,cvs,xys); - - end - end - end - + paint_marks(mk,cvs,xys); + end + inherited; + end + function get_legend_size(w,h);virtual; + begin + mk := markinfo; + h := fontinfo.size+4; + w := 100; + if mark_mode=tgc_on then + begin + h := max(10,mk.size+4); + w := 5*h; + end + end + function paint_legend(cvs,rec);override; //»æÖÆÍ¼Àý + begin + y0 := ceil(rec[1]+(rec[3]-rec[1])/2); + dis := ceil((rec[2]-rec[0])/5); + xys := array((rec[0]+dis,y0),(rec[0]+4*dis,y0)); + set_lineinfo_to_canvas(cvs); + paint_lines(cvs,tgc_LS_interpolated,xys,0,array("line_mode":fline_mode,"bar_width":fbar_width,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor)); + mk := markinfo; + if mark_mode=tgc_on and mk.size>2 then + begin + xys := array((rec[0]+dis*2,y0),(rec[0]+3*dis,y0)); + paint_marks(mk,cvs,xys); + end + end property closed read fclosed write fclosed;//= "off" - //property mark_style read fmark_style write fmark_style;//= "dot" - //property mark_size_unit read fmark_size_unit write fmark_size_unit;//= "point" - //property mark_size read fmark_size write fmark_size;//= "0" - //property mark_foreground read fmark_foreground write fmark_foreground;//= "0" - //property foreground read fforeground write fforeground;//= "0" - //property mark_background read fmark_background write fmark_background;//= "0" - //property background read fbackground write fbackground;//= "0" - property line_mode read fline_mode write fline_mode;//= "0" - property mark_mode read fmark_mode write fmark_mode;//= "0" - property polyline_style read fpolyline_style write fpolyline_style;//= "0" - property bar_width read fbar_width write fbar_width;//= "0" - property data read fdata write set_data; + property line_mode read fline_mode write set_line_mode;//= "0" + property mark_mode read fmark_mode write set_mark_mode;//= "0" + property polyline_style read fpolyline_style write set_polyline_style;//= "0" + property bar_width read fbar_width write fbar_width;//= "0" private fdata_bounds; fclosed; - fmark_size_unit; - fmark_style; - fmark_size; - fmark_foreground; - fmark_background; fforeground; fbackground; fline_mode; fmark_mode; fpolyline_style; fbar_width; - fdata;//Êý¾Ý //datatips;//: ["Datatip";"Datatip"] //datatip_display_mode;//: "always" //display_function ;//= "" //display_function_data ;//= [] //fill_mode ;//= "off" //thickness ;//= 4 - //arrow_size_factor ;//= 1 - + //arrow_size_factor ;//= 1 //interp_color_vector ;//= [] //interp_color_mode ;//= "off" - //colors ;//= [] - + //colors ;//= [] //mark_offset ;//= 0 //mark_stride ;//= 1 //x_shift ;//= [] @@ -1397,44 +2331,68 @@ type tg_Polyline = class(tg_graph) //bar_width ;//= 0 //clip_state ;//= "clipgrf" //clip_box ;//= [] - private - fx; - fy; - function set_data(d); //ÉèÖÃÊý¾Ý + protected + function set_graph_data(d);override; //ÉèÖÃÊý¾Ý begin - if d<>FData then + if d<>fgraph_data then begin - FData := d; - fx := fdata[:,0]; - fy := fdata[:,1]; + fx := d[:,0]; + fy := d[:,1]; fdata_bounds[0,0] := minvalue(fx); fdata_bounds[1,0] := minvalue(fy); fdata_bounds[0,1] := maxvalue(fx); fdata_bounds[1,1] := maxvalue(fy); - prop_changed("data",v); + inherited; end end -end - + private + function set_polyline_style(v); + begin + if v<>fpolyline_style then + begin + fpolyline_style := v; + end + end + function set_line_mode(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fline_mode then + begin + fline_mode := nv; + end + end + function set_mark_mode(v); + begin + if not tg_boolen_value(v,nv) then return ; + if nv<>fmark_mode then + begin + fmark_mode := nv; + end + end +end type tg_line_info = class(tg_const) function create(); begin fcolor := 0; FWidth := 1; FStyle := tgc_PS_SOLID; + fbkcolor := nil; end - property width read FWidth write fwidth; - property color read fcolor write fcolor; property Style read FStyle write FStyle; + property width read FWidth write fwidth; + property size read FWidth write fwidth; + property color read fcolor write fcolor; + property bkcolor read fbkcolor write fbkcolor; private fwidth; fcolor; FStyle; + fbkcolor; end type tg_font_info = class(tg_const) function create(); begin - fstyle := tgc_mks_dot; + fstyle := nil; fsize := 7; fforeground := 0; fbackground := nil; @@ -1476,11 +2434,23 @@ type tg_base = class(TNode,tg_const) // function create(pms); begin class(TNode).create(); - fvisibe := true; + fvisibe := tgc_on; flineinfo := new tg_line_info(); fmarkinfo := new tg_mark_info(); ffontinfo := new tg_font_info(); end + function axes_mapping(x,y,z,_x,_y);virtual; + begin + p := get_axes(); + if p then return p.axes_mapping(x,y,z,_x,_y); + return false; + end + function axes_unmapping(x,y,z,_x,_y);virtual; + begin + p := get_axes(); + if p then return p.axes_unmapping(x,y,z,_x,_y); + return false; + end function Coordinate_Mapping(x,y,z,_x,_y);virtual; begin p := get_axes(); @@ -1499,19 +2469,59 @@ type tg_base = class(TNode,tg_const) // end function paint(cvs);virtual; //»æÖÆ begin - if not visible then return ; + if tgc_on<> visible then return ; for i := 0 to NodeCount-1 do begin vi := GetNodeByIndex(i); vi.paint(cvs); end - end + end + function set_lineinfo_to_canvas(cvs,info); + begin + if info is class(tg_line_info) then li := info; + else + li := lineinfo; + cl := li.color; + cvs.pen.style := li.style; + if ifnumber(cl) then + begin + cvs.pen.color := cl; + end else + begin + cvs.pen.Style := tgc_BS_NULL; + end + cvs.pen.width := li.width; + bcl := li.bkcolor; + if ifnumber(bcl) then + begin + cvs.brush.color := li.bkcolor; + cvs.brush.Style := tgc_BS_SOLID; + end + else + begin + cvs.brush.Style := tgc_BS_NULL; + end + end + function set_fontinfo_to_canvas(cvs,info); + begin + if info is class(tg_font_info) then fi := info; + else + fi := fontinfo; + cvs.font.color := fi.color; + cvs.font.bkcolor := fi.bkcolor; + cvs.font.width := fi.size; + cvs.font.height := fi.size*2; + end published property axes read get_axes write set_axes; property visible read fvisibe write setvisible; property lineinfo read flineinfo; property markinfo read fmarkinfo; property fontinfo read ffontinfo; + + public + user_data; + tag; protected function get_axes();virtual; begin @@ -1520,23 +2530,32 @@ type tg_base = class(TNode,tg_const) // end function set_axes(axs);virtual; begin - end - public - user_data; - tag; - protected + end function check_parent(p);virtual; //¸¸½Úµã¼ì²é begin return true; end function prop_changed(n,v);virtual; //¸Ä±ä֪ͨ begin - + axs := get_axes(); + if axs then fg := axs.figure; + if fg then + begin + fg.executecommand("figure_need_fresh",p); + end end function SetParent(V);virtual; begin - if not check_parent(p) then return ; - return inherited; + if not check_parent(v) then return ; + if v then ct := v.NodeCount; + r := inherited; + if v then ct2 := v.NodeCount; + if ct2>ct then + begin + ax := axes; + if ax then ax.executecommand("node_add_in",self(true)); + end + return r; end private fvisibe; @@ -1545,8 +2564,7 @@ type tg_base = class(TNode,tg_const) // ffontinfo; function setvisible(v);//ÉèÖÿɼû begin - nv := v?true:false; - if nv<>fvisibe then + if tg_boolen_value(v,nv) and (nv<>fvisibe) then begin fvisibe := nv; prop_changed("visible",fvisibe); @@ -1554,24 +2572,24 @@ type tg_base = class(TNode,tg_const) // end end type tg_const = class() - - static const tgc_top = "top"; - static const tgc_bottom = "bottom"; - static const tgc_left = "left"; - static const tgc_right = "right"; - static const tgc_middle = "middle"; - static const tgc_origin = "origin"; - + ////////////»ù´¡/////////////////// static const tgc_off = "off"; static const tgc_on = "on"; static const tgc_box_off = "off"; static const tgc_box_on = "on"; static const tgc_box_half = "half"; + /////////////×ø±êÖá/////////////////// + static const tgc_top = "top"; + static const tgc_bottom = "bottom"; + static const tgc_left = "left"; + static const tgc_right = "right"; + static const tgc_middle = "middle"; + static const tgc_origin = "origin"; static const tgc_box_hidden_axes = "hidden_axes"; - static const tgc_t_s_v = "v"; - static const tgc_t_s_r = "r"; - static const tgc_t_s_i = "i"; - + static const tgc_tics_v = "v"; + static const tgc_tics_r = "r"; + static const tgc_tics_i = "i"; + //////±ê¼ÇÀàÐÍ////////////////////// static const tgc_mks_dot = "dot"; //Ô­µã static const tgc_mks_plus = "plus"; //¼ÓºÅ static const tgc_mks_star = "star"; //Ȧ²æ @@ -1585,31 +2603,48 @@ type tg_const = class() static const tgc_mks_triangle_up = "triangle_up"; static const tgc_mks_triangle_down = "triangle_down"; static const tgc_mks_triangle_left = "triangle_left"; - static const tgc_mks_triangle_right = "triangle_right"; - + static const tgc_mks_triangle_right = "triangle_right"; static const tgc_mk_tabulated = "tabulated"; static const tgc_mk_point = "point"; - - static const tgc_dm_always = "always"; - static const tgc_dm_mouseclick = "mouseclick"; - static const tgc_dm_mouseover = "mouseover"; - + /////////////////Êý¾ÝÌáʾÀàÐÍ//////////////////////////////////// + static const tgc_DT_always = "always"; + static const tgc_DT_mouseclick = "mouseclick"; + static const tgc_DT_mouseover = "mouseover"; + ////////////»­±Ê»­Ë¢ÀàÐÍ///////////////////////////////// static const tgc_PS_SOLID=0x0; static const tgc_PS_DASH=0x1; static const tgc_PS_DOT=0x2; static const tgc_PS_DASHDOT=0x3; static const tgc_PS_DASHDOTDOT=0x4; static const tgc_PS_NULL=0x5 ; + static const tgc_BS_NULL=1; + static const tgc_BS_SOLID=0; - static const tgc_LS_interpolated="interpolated" ; - static const tgc_LS_staircase="staircase" ; - static const tgc_LS_arrowed="arrowed" ; - static const tgc_LS_barplot="barplot" ; - static const tgc_LS_filled="filled" ; - static const tgc_LS_bar="bar" ; + ///////////////////ÏßÐÍ/////////////////////////////// + static const tgc_LS_interpolated="interpolated"; + static const tgc_LS_staircase="staircase"; + static const tgc_LS_arrowed="arrowed"; + static const tgc_LS_barplot="barplot"; + static const tgc_LS_filled="filled"; + static const tgc_LS_bar="bar"; + + /////////////////Ïà¶ÔλÖÃ//////////////////////////// + static const tgc_in_upper_right = "in_upper_right"; + static const tgc_in_upper_left = "in_upper_left"; + static const tgc_in_lower_right = "in_lower_right"; + static const tgc_in_lower_left = "in_lower_left"; + static const tgc_upper_caption = "upper_caption"; + static const tgc_lower_caption = "lower_caption"; + static const tgc_by_coordinates = "by_coordinates"; + static const tgc_by_axes = "by_axes"; + //static const tgc_out_upper_right = "out_upper_right"; + //static const tgc_out_upper_left = "out_upper_left"; + //static const tgc_out_lower_right = "out_lower_right"; + //static const tgc_out_lower_left = "out_lower_left"; + ////////////// end implementation -function mg_bds(bds,d); +function mg_bds(bds,d); //ºÏ²¢Êý¾ÝÉÏϽç begin d[0,0] := min(bds[0,0],d[0,0]); d[0,1] := max(bds[0,1],d[0,1]); @@ -1618,13 +2653,110 @@ begin d[2,0] := min(bds[2,0],d[2,0]); d[2,1] := max(bds[2,1],d[2,1]); end -function p_trans(x,y,ag,_x,_y); +function p_trans(x,y,ag,_x,_y);//Ðýת begin _x := x*cos(ag)+y*sin(ag); _y := -x*sin(ag)+y*cos(ag); end -function paint_marks(mk,dc,xys); +function paint_lines(cvs,pls,xys,cls,ifo);//»®Ïß begin + o := static new tg_const(); + case pls of + o.tgc_LS_staircase: + begin + if ifo["line_mode"]<>o.tgc_on then return ; + last := array(); + for i,v in xys do + begin + if i=0 then + begin + last := v; + cvs.moveto(v); + end else + begin + cvs.lineto(array(v[0],last[1])); + cvs.lineto(v); + last := v; + end + end + end + o.tgc_LS_barplot: + begin + for i,v in xys do + begin + cvs.moveto(array(v[0],v[1])); + cvs.lineto(array(v[0],ifo["y"])); + end + paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo); + end + o.tgc_LS_bar: + begin + b_w := integer(ifo["bar_width"]/2); + cvs.brush.color := ifo["bkcolor"]; + for i,v in xys do + begin + if b_w>=1 then + begin + v1 := array(v[0]-b_w,v[1]); + v2 := array(v[0]+b_w,v[1]); + v3 := array(v[0]+b_w,ifo["y"]); + v4 := array(v[0]-b_w,ifo["y"]); + cvs.draw_polygon().points(array(v1,v2,v3,v4)).draw(); + end else + begin + cvs.moveto(array(v[0],v[1])); + cvs.lineto(array(v[0],ifo["y"])); + end + end + paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo); + end + o.tgc_LS_arrowed: + begin + if ifo["line_mode"]<>o.tgc_on then return ; + paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo); + vlast := xys[0]; + for i,v in xys do + begin + if i<1 then continue; + x := v[0]; + y := v[1]; + dx := x-vlast[0]; + dy := y-vlast[1]; + arg := arctan(dy/dx)+pi(); + sz := 15; + p_trans(sz,0,-(arg-pi()/6),x1,y1); + cvs.moveto(v); + cvs.lineto(array(v[0]+x1,v[1]+y1)); + p_trans(sz,0,-(arg+pi()/6),x1,y1); + cvs.moveto(v); + cvs.lineto(array(v[0]+x1,v[1]+y1)); + vlast := v; + end + end + o.tgc_LS_filled: + begin + cvs.brush.color := ifo["color"]; + for i,v in xys do + begin + if i=0 then continue; + v1 := v; + v2 := array(v[0],ifo["y"]); + v4 := xys[i-1]; + v3 := array(v4[0],ifo["y"]); + cvs.draw_polygon().points(array(v1,v2,v3,v4)).draw(); + end + paint_lines(cvs,o.tgc_LS_interpolated,xys,ifo); + end + else + begin + if ifo["line_mode"]<>o.tgc_on then return ; + cvs.draw_polyline().points(xys union ((cls=o.tgc_on and length(xys)>2)?array(xys[0]):array())).draw(); + end + end +end +function paint_marks(mk,dc,xys); //»æÖƵã +begin + o := static new tg_const(); tp := mk.Style; sz := mk.size; a := integer(sz/2); @@ -1632,9 +2764,10 @@ begin a := b; dc.pen.Style := 0; dc.pen.color := mk.color; + dc.brush.style := 0; dc.brush.color := mk.bkcolor; case tp of - "pentagram": + o.tgc_mks_pentagram: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1652,7 +2785,7 @@ begin sp.points(vv).draw(); end end - "triangle_up": + o.tgc_mks_triangle_up: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1665,7 +2798,7 @@ begin sp.points(array(v1,v3,v2)).draw(); end end - "triangle_down": + o.tgc_mks_triangle_down: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1677,8 +2810,8 @@ begin v3 := array(v[0]+_x,v[1]+_y); sp.points(array(v1,v3,v2)).draw(); end - end - "triangle_left": + end + o.tgc_mks_triangle_left: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1691,7 +2824,7 @@ begin sp.points(array(v1,v3,v2)).draw(); end end - "triangle_right": + o.tgc_mks_triangle_right: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1704,15 +2837,15 @@ begin sp.points(array(v1,v3,v2)).draw(); end end - "diamond_plus": + o.tgc_mks_diamond_plus: begin - mk.Style := "diamond"; + mk.Style := o.tgc_mks_diamond ; paint_marks(mk,dc,xys); - mk.Style := "plus"; + mk.Style := o.tgc_mks_plus; paint_marks(mk,dc,xys); - mk.Style := "diamond_plus"; - end - "diamond": + mk.Style := o.tgc_mks_diamond_plus; + end + o.tgc_mks_diamond: begin sp := dc.draw_polygon(); for i,v in xys do @@ -1727,11 +2860,11 @@ begin end end - "dot","circle","squre": + o.tgc_mks_dot,o.tgc_mks_circle,o.tgc_mks_square: begin - if tp="dot" then + if tp=o.tgc_mks_dot then dc.brush.color := mk.color; - if tp="squre" then pse := dc.draw_rect(); + if tp=o.tgc_mks_square then pse := dc.draw_rect(); else pse := dc.draw_ellipse(); for i,v in xys do @@ -1740,7 +2873,7 @@ begin pse.rect(rec).draw(); end end - "plus": + o.tgc_mks_plus: begin for i,v in xys do begin @@ -1756,15 +2889,15 @@ begin dc.lineto(v4); end end - "star": + o.tgc_mks_star: begin - mk.Style := "circle"; + mk.Style := o.tgc_mks_circle; paint_marks(mk,dc,xys); - mk.Style := "plus"; + mk.Style := o.tgc_mks_plus; paint_marks(mk,dc,xys); - mk.Style := "star"; + mk.Style := o.tgc_mks_star; end - "cross": + o.tgc_mks_cross: begin for i,v in xys do begin @@ -1779,17 +2912,136 @@ begin dc.moveto(v3); dc.lineto(v4); end - end - "asterisk": + end + o.tgc_mks_asterisk: begin - mk.Style := "cross"; + mk.Style := o.tgc_mks_cross; paint_marks(mk,dc,xys); - mk.Style := "plus"; + mk.Style := o.tgc_mks_plus; paint_marks(mk,dc,xys); - mk.Style := "asterisk"; + mk.Style := o.tgc_mks_asterisk; end end ; end +function tg_boolen_value(v,nv); //¹æÔò»¯boolean +begin + if v=true or v="on" then + begin + nv := "on"; + return true; + end else + if v=false or v="off" then + begin + nv := "off"; + return true; + end +end +////////////////±ß½çÈ¡Õû//////////////////////////// +function new_bound_factor(a,n); +begin + if a>1 and a<=10 then + begin + return int(a)*10^n; + end else + if a>10 then + begin + n++; + return new_bound_factor(a/10,n); + end else + if a<=1 then + begin + n--; + return new_bound_factor(a*10,n); + end +end +function new_bounds(a,b,a_,b_,par); +begin + a_ := a; + b_ := b; + if not(par>=1) then par:=20;//20; + r := new_bound_factor((b-a)/par,n); + if r<>0 then + begin + a_:=floor(a/r)*r; + b_:= ceil(b/r)*r; + end + return r; +end +function get_node_data_bounds(nd); //»ñÈ¡½ÚµãµÄ·¶Î§ +begin + d := zeros(3,2); + for i := 0 to nd.NodeCount-1 do + begin + vi := nd.GetNodeByIndex(i); + if vi is class(tg_graph_base) then + begin + bds := vi.get_data_bounds(); + mg_bds(bds,d); + end + end + return d; +end +function get_rect_at_corner(x,y,w,h,itv,flg,mvx,mvy); //¼ÆËãÎ§ÈÆµãµÄÇøÓòλÖà +begin + //0×óÉÏ £¬1ÓÒÉÏ 2 ÓÒÏ 3 ×óÏ + r := zeros(4); + case flg of + 0: + begin + r[0] :=x-w-itv; + r[1] :=y-h-itv; + r[2] :=x-itv; + r[3] :=y-itv; + end + 1: + begin + r[0] :=x+itv; + r[1] :=y-h-itv; + r[2] :=x+w+itv; + r[3] :=y-itv; + end + 2: + begin + r[0] :=x+itv; + r[1] :=y+itv; + r[2] :=x+w+itv; + r[3] :=y+h+itv; + end + 3: + begin + r[0] :=x-w-itv; + r[1] :=y+itv; + r[2] :=x-itv; + r[3] :=y+h+itv; + end + 4: //ÖÐ + begin + w2 := ceil(w/2); + h2 := ceil(h/2); + r[0] :=x-w2; + r[1] :=y-h2; + r[2] :=x+w2; + r[3] :=y+h2; + end + + end; + if mvx>0 or mvx<0 then + begin + r[0]+=mvx; + r[2]+=mvx; + end + if mvy>0 or mvy<0 then + begin + r[1]+=mvy; + r[3]+=mvy; + end + return r; +end +function rec_to_points(rec); +begin + return array(rec[array(0,1)],rec[array(2,1)],rec[array(2,3)],rec[array(0,3)],rec[array(0,1)]); +end +//////////////////////////////////////// initialization finalization