From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,95dad6602b955ce1 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!newsread.com!newsprint.newsread.com!news.glorb.com!border1.nntp.dca.giganews.com!nntp.giganews.com!local01.nntp.dca.giganews.com!nntp.megapath.net!news.megapath.net.POSTED!not-for-mail NNTP-Posting-Date: Fri, 14 Oct 2005 18:43:55 -0500 From: "Randy Brukardt" Newsgroups: comp.lang.ada References: <1129043820.987947.200870@z14g2000cwz.googlegroups.com> <1129136767.955381.143030@g47g2000cwa.googlegroups.com> <1129215004.069760.84050@g49g2000cwa.googlegroups.com> <1129220290.938615.36390@o13g2000cwo.googlegroups.com> <1129302185.489627.266900@g47g2000cwa.googlegroups.com> Subject: Re: Problem with "limited with" in a *real* application Date: Fri, 14 Oct 2005 18:47:57 -0500 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4952.2800 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4952.2800 Message-ID: NNTP-Posting-Host: 64.32.209.38 X-Trace: sv3-Zldn2q+ZFaXb3Rxj7NJBBjRArZx1LUvg7bp6shPNOqbFFGrpP03YhGjOStm1+jT8H8+CX4wN5IxyPU3!i/PrTkvpz/gA9j6K/A41MN5gYCrswHf+J8uy26agPoQVmbycGG4cdbI/q406G4RsdTXHUcBt4PsX!tIUONh5HQRS6BA== X-Complaints-To: abuse@megapath.net X-DMCA-Complaints-To: abuse@megapath.net X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.32 Xref: g2news1.google.com comp.lang.ada:5671 Date: 2005-10-14T18:47:57-05:00 List-Id: "Lucretia" wrote in message news:1129302185.489627.266900@g47g2000cwa.googlegroups.com... > Inside the Sizer package I have an Add procedure which adds a > Window_Type (e.g. Button_Type, Check_Box_Type, etc) into the derived > type to Self, which is a Sizer_Type derived type. So, I want (ideally) > to minimize the casting, so I changed the Window type to take a > Window_Type'Class so that any type can be accepted. Now, this forces me > to cast the Self type in the New_Minimal_Frame procedure (See the > Add's) to the base Sizer_Type. Now in C++ the Add function can be > overridden (as in the case of wxGridBagSizer and they're not virtuals) > so in the case of mapping to Ada in this current form, the programmer > must know which Add to use, i.e. which cast to use, which is fair > enough, but surely it would be easier to let the compiler decide? > Should I use a 'Class type here? Probably not. If you need overriding and/or dispatching somewhere, you'll want to avoid 'Class. My rule of thumb is that primitives should be specific unless you're absolutely certain that you'll never want to override them in any child types. (And when is that true?). You have to use a (view) type conversion (what you've been calling a "cast") to all the operations of the parent type. That's just the way you write that in Ada. OTOH, it's usually not necessary to do that for most operations, because they are inherited, and you can just call them for the type itself. > So, with this in mind, it's a possibility that all of the wxAda > primitives could take 'Class types so that no casting is ever needed, > but surely this is wrong, Ada-wise? It's probably wrong, but I'd have to see your entire design to know for sure. Which I'd rather not do... > The format of the following code might get a bit screwed by Google: > > > package wx.Core.Sizer is > > -- This is the actual type (wxSizer) we are creating here. > type Sizer_Type is new Object_Type with private; -- All of the (primitive) operations of the parent type are inherited here, -- so you can call them without using any type conversions. > procedure Add( > Self : in out Sizer_Type; > Window : in Window_Type'Class; > Proportion : in Sizer_Proportion_Type := 0; > Flags : in Sizer_Flag_Type := 0; > Border : in Integer := 0); > > end wx.Core.Sizer; > > > > package body Minimal_Frame is > > procedure New_Minimal_Frame(Self : in out Minimal_Frame_Type) is > > procedure Button_Connect is new > wxEvtHandler.Connect(Command_Event_Function); > procedure Check_Box_Connect is new > wxEvtHandler.Connect(Command_Event_Function); > procedure My_Test_Connect is new > wxEvtHandler.Connect(On_My_Test_Function); > procedure Slider_Connect is new > wxEvtHandler.Connect(Scroll_Event_Function); > procedure Size_Connect is new > wxEvtHandler.Connect(Size_Event_Function); > procedure Paint_Connect is new > wxEvtHandler.Connect(Paint_Event_Function); > > Field_Widths : Field_Widths_Array(0 .. 1) := (-3, -1); > > package Address_To_Object is new > System.Address_To_Access_Conversions(Minimal_Frame_Type); > use Address_To_Object; > > begin > > New_Frame(Self, ID_ANY, "Minimal wxAda App", Point_Type'(400, > 300)); > Text_IO.Put_Line("Self'Access : " & > System.Address_Image(To_Address(Self'Access))); > > New_Panel(Self.Panel, Window_Type(Self), Id_Any); Here, the second parameter of New_Panel probably should be class-wide. A subprogram with two specific different tagged types as parameters is almost always wrong. (Dmitry will tell you why in excrutating details if you want to know. :-) > New_Validator(Self.Validator); > > New_Button(Self.Button, Window_Type(Self.Panel), > Id_Type(Id_Test_Button), "Test &Button", Default_Position, > Default_Size, 0); Same is true here. In Claw, the Create routines look something like: procedure Create (Button : in out Button_Type; Parent : in out Root_Window_Type'Class; Size : in Size_Type; Position : in Point_Type; ....); > Set_Validator(Window_Type(Self.Button), Self.Validator); Presuming that this is an operation on the root window type, you should be able to just call this (a Button will have inherited it). Set_Validator (Self.Button, Self.Validator); (or, in C++-like notation in Ada 200Y:) Self.Button.Set_Validator (Self.Validator); The latter notation avoids the need for use-clauses. If this isn't an operation on the root window type, then there is something wrong with your design. Either the prefix should be class-wide (and no type conversion is needed), or it should be primitive so it is inherited (and thus can be overridden) by other tagged types (window classes). > New_Check_Box(Self.Check_Box, Window_Type(Self.Panel), Id_Any, > "Test &Check Box", Style => Check_Box_Align_Right); > New_Slider(Self.Slider, Window_Type(Self.Panel), Id_Any, 50, 0, > 100, Style => Slider_Horizontal or Slider_Labels); > New_Spin(Self.Spin, Window_Type(Self.Panel), Id_Any, "0", Style => > Spin_Wrap or Spin_Arrow_Keys); > New_Scroll_Bar(Self.Scroll_Bar, Window_Type(Self.Panel), > Id_Type(Id_Test_Slider)); > Set_Scroll_Bar(Self.Scroll_Bar, 20, 10, 100, 1000); > > New_Static_Box(Self.Box, Window_Type(Self.Panel), Id_Any, > "Testing..."); > New_Static_Box_Sizer(Self.Sizer, Self.Box'Unchecked_Access, > Box_Sizer_Orientation_Vertical); > --New_Box_Sizer(Self.Sizer, Box_Sizer_Orientation_Vertical); > Add(Sizer_Type(Self.Sizer), Self.Button, 1, Sizer_Expand or > Sizer_Border_All, 5); > Add(Sizer_Type(Self.Sizer), Self.Check_Box, 1, Sizer_Expand or > Sizer_Border_All, 5); > Add(Sizer_Type(Self.Sizer), Self.Slider, 1, Sizer_Expand or > Sizer_Border_All, 5); > Add(Sizer_Type(Self.Sizer), Self.Spin, 1, Sizer_Expand or > Sizer_Border_All, 5); > Add(Sizer_Type(Self.Sizer), Self.Scroll_Bar, 1, Sizer_Expand or > Sizer_Border_All, 5); I don't see any need for the conversions to Sizer_Type here. If Self.Sizer is derived from Sizer_Type, then Add is inherited. Use that one without a conversion. (That way, if it becomes necessary to override it in the future, you'll use the overriding version for the type.) If it is actually Sizer_Type, you don't need it. The only problem is figuring out where the routine ("Add" in this case) is declared, because you can't see inherited declarations. There are a number of solutions to that: 1) Have a use_clause for every package that declares a type that you use. (I hate this one myself.) 2) Use dot notation to specify that the routine comes from the package where the type is declared; 3) or use the prefixed view call notation introduced by Ada 200Y: Self.Sizer.Add (Self.Scroll_Bar, 1, Sizer_Expand or Sizer_Border_All, 5); > New_Status_Bar(Self.Status_Bar, Window_Type(Self), Id_Any); > Set_Fields_Count(Self.Status_Bar, Field_Widths); > Set_Status_Bar(Self, Self.Status_Bar); > Set_Status_Text(Self.Status_Bar, "Welcome to wxAda!"); > -- Set_Status_Widths(Test_Status_Bar, Field_Widths'Length, > Field_Widths); > > Set_Size_Hints(Sizer_Type(Self.Sizer), > Self.Panel'Unchecked_Access); > -- Set_Sizer(Window_Type(Self.Panel), Self.Sizer'Unchecked_Access); > Set_Sizer(Window_Type(Self.Panel), Sizer_Type(Self.Sizer)'Access); > -- Set_Sizer(Self.Panel, Sizer_Type(Self.Sizer)); > > Test_Event.New_Test_Event(Self.My_Test); > > --Button_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any, > wx.Base.Event.Command.Button_Clicked, On_Quit'Access); > Button_Connect(Self, Id_Type(Id_Test_Button), Id_Any, > Evt_Button_Clicked, On_Quit'Access); > --Check_Box_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any, > wx.Base.Event.Command.Check_Box_Clicked, On_Quit'Access); > Slider_Connect(Self, Id_Type(Id_Test_Slider), Id_Any, > Evt_Scroll_Thumb_Track, On_Scroll_Top'Access); > Size_Connect(Self, Id_Any, Id_Any, Evt_Size, On_Size'Access); > --Paint_Connect(Self.Panel, Id_Any, Id_Any, Evt_Paint, > On_Paint'Access); > Dump(Self); > My_Test_Connect(Self, Id_Any, Id_Any, Test_Event.My_Test_Event, > On_My_Test'Access); > > end New_Minimal_Frame; > > end Minimal_Frame; > Hope this helps. Randy.