DELPHI.. Create Multiple tabsheet with same child control at runtime [duplicate] - oop

I often embed a TForm descendant into another TForm descendant like this:
var
Form1: TForm1;
Form2: TForm2;
begin
Form2.Parent := Form1;
Form2.BorderStyle := bsNone;
Form2.Align := alClient;
Form2.Show;
end;
Usually this works just fine, but sometimes the controls in Form2 are not aligned properly. Is there a general workaround for this sort of problem?
Does anybody know what is causing this "misalignment"?
I know that I could use TFrame for this kind of job, but I have a lot of library code that I would have to rewrite and I do not see any reason why the TForm in TForm approach should not work?
Edit: I have identified the component TcxListView as the culprit here, I have submitted a bug report to the component vendor (DevExpress):
http://www.devexpress.com/issue=B194161
Edit 2: The developers at DevExpress have analyzed the problem and said that it is actually a defect in the TGridPanel component by Embarcadero:
http://qc.embarcadero.com/wc/qcmain.aspx?d=90324

I do this as well and I use the following routine to make it happen:
procedure TMyForm.PlaceInsideContainer(Container: TWinControl);
begin
Parent := Container;
Align := alClient;
BorderIcons := [];
BorderStyle := bsNone;
ParentBackground := True;
Show;
end;
I have no problems with this. The only difference that I could possibly imagine could be relevant is the assignment of BorderIcons, but I would doubt that causes a problem.

I read a similar question (you'll have to google it) and the answer from TeamB was not to do this as the behaviour was unpredictable and that you should use TFrame instead (which is what I have always done).

Related

Why does direct binding of an `our &foo` not work, but indirecting via a dynamic lookup does?

Why is there a difference between r1 and r2 when called outside of module TEST?
module TEST {
our &r1 := OUR::{'&r1'} := sub {
say 'routine 1'
}
r1(); # routine 1
our &r2 := sub {
say 'routine 2'
}
r2(); # routine 2
}
import TEST;
say TEST::.keys; # (&r1 &r2)
TEST::r1(); # routine 1
TEST::r2(); # Cannot invoke this object (REPR: Uninstantiable; Callable) ...
There is an error when trying to run subroutine r2 outside of module TEST where it was defined.
TL;DR Binding to an our is pointless. Binding to an OUR::<&foo> is effective. I like naming things... It seems you've invented a technique which I hereby dub "#jakar's double bind our".
Why the direct binding only works inside the module
In a comment on his answer to an earlier SO jnthn concludes that we could perhaps have an error message, or perhaps a warning, to the effect that:
binding to an our variable is pointless use of our.
(What he means is that the binding only works inside the module, not outside, as you have discovered.)
There's an old and still open issue Binding a variable at BEGIN time doesn't stick around for runtime that discusses the general problem in depth.
Why the dynamic lookup works outside the module
From Symbols that start with core namespaces always get exported, jnthn notes that:
stashes are always open to poke symbols in to.
So, ignoring use of symbols inside your module, your code is doing this:
module TEST {
OUR::{'&r1'} := sub { say 'routine 1' }
our &r2;
}
import TEST;
TEST::r1(); # routine 1
TEST::r2(); # Cannot invoke this object (REPR: Uninstantiable; Callable) ...
#jakar's double bind our
If one wants to be able to declare a symbol and use it both inside and outside the module and insists on using binding then your trick of declaring it with a double bind may be the best technique available:
our &r1 := OUR::{'&r1'} := sub { ... }
^^^^^^^^^^^^^^^^^^^^^^^^^^^ works *outside* module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ works *inside* module
Some things I'm curious about:
Have you been able to confirm any significant specific and practical advantage(s) that can be accrued from binding instead of assigning an our?
Do folk want to get around the "binding to an our variable is pointless" issue? If so, would they be happy to use #jakar's double bind our?
Does your technique apply to all sigils? (I would expect so but will leave it to you to explore such aspects. :))

Is there any delayed MultiCast-Event, which is able to be interruptable?

I am looking for an interruptable, delayed event, which I hope could be already part of Spring4D, or easily implemented there.
What would be best way anyway, to achieve this ?
Probably the Event wouldn't be the right place.
Basically looking for something like
Event.InvokeDelayed(1000, nil); and
Event.InvokeCancel;
procedure TTestMulticastEvent.Test;
var
e: Event<TNotifyEvent>;
begin
e.Add(HandlerA);
e.Invoke(nil); // Yes, this is the normal behaviour
// But would this make sense in Events,
// or better use other concept, like TTask.IdleWorker, e.g. ?
e.InvokeDelayed(1000, nil); // waits 1sec
Sleep(100); // Interrupts after 100ms
e.InvokeCancel; // Prevent future Event, started earlier
end;
Maybe I oversee something already available to solve this task in S4D.
Rollo
No, multicast events as they are in the library are synchronous. For them to work properly asynchronously in all cases it would require way more than just delaying their invokation but capturing any data you pass through them, make sure that data does not get invalid and so on.
If you need a mechanism like that you should use one of the existing libraries out there to do asynchronous things.
For example with the PPL (naive code to just show the concept):
var
e: Event<TNotifyEvent>;
t: ITask;
begin
e.Add(HandlerA);
t := TTask.Run(
procedure
begin
Sleep(1000);
if t.Status <> TTaskStatus.Canceled then
TThread.Synchronize(nil,
procedure
begin
e.Invoke(nil);
end);
end);
Sleep(100);
t.Cancel;
end;
You can probably wrap this into your own routine depending on your needs and the actual implementation. It will not be possible however to make a InvokeDelayed method with an additional parameter to what the event type has as signature because Event<T>.Invoke is not a method but a property returning T which you can invoke (which makes it look like a method call itself).
Anything beyond that requires as I said preserving the parameters passed to Invoke to pass them later (something that anonymous methods to for you to a certain degree) which is not trivial (at least not when we are talking about the generic Event<T>)

How to return a Forward_Iterator of a Hashed_Set in Ada?

I want to return a Forward_Iterator over the elements of an hashed_set in Ada, like in the code below:
with Ada.Containers.Hashed_Sets;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Hash;
with Ada.Text_IO; use Ada.Text_IO;
procedure debug is
package my_set is new Ada.Containers.Hashed_Sets
(Element_Type => Unbounded_String,
Hash => Ada.Strings.Unbounded.Hash,
Equivalent_Elements => "=");
function get_Iterator
(some_set : my_set.set)
return my_set.Set_Iterator_Interfaces.Forward_Iterator'Class is --' Highlight fix
begin
return some_set.Iterate;
end;
set_1 : my_set.set;
begin
set_1.insert(To_Unbounded_String("element"));
for E in get_Iterator (some_set => set_1) loop
put_line ("i iterate!");
end loop;
end debug;
The problem is that the code raises a program error
"raised PROGRAM_ERROR : debug.adb:6 finalize/adjust raised exception" which i do not understand ... (im using GNAT Ada GPL 2014 under Ubuntu 14.04)
Is there a way to repair the code? Or is there another possibility to return an iterator over a hashed_set? An application for this is e.g. the case when the hashed_set is part of an private record and it should only be possible to iterate the elements from outside, but not to change the set itself.
Thanks in advance!
PS: This is my first question here, so if you have any tips for improving the question, please tell me :)
I think you have found a bug in GNAT. Please submit your example to the GCC bug database.
But why do you want an explicit iterator object? Usually you just loop over the container leaving the compiler to mess with handling the iterator object.
I just wanted to post my solution to this problem.
I had the possiblity to check the problem with Gnat Pro 7.2.x and I does not appear anymore. But If you do I similar approach using a Hashed_Map instead of a Hashed_Set, it was still there.
Since I also got access to the GNATtracker, I postet my problem there and was told that this is indead a compiler bug. The compiler is generating an incorrect accessibility check at the Get_Iterator function.
Hence, the workaround that was suggested, was to just suppress the corresponding check for the function:
function get_Iterator
(some_set : my_set.set)
return my_set.Set_Iterator_Interfaces.Forward_Iterator'Class is --' Highlight fix
pragma Suppress (Accessibility_Check); -- workaround to suppress buggy check
begin
return some_set.Iterate;
end;
This workaround works for me with Gnat Pro 7.2.x and Gnat GPL 2014 for both, Hashed_Sets and Hashed_Maps.

Upcasting accesses

Let's say I have a Planet:
type Planet is tagged null record;
type Planet_Ref is access Planet'class;
Now I subclass it:
type Habitable_Planet is new Planet with null record;
type Habitable_Planet_Ref is access Habitable_Planet'class;
Now I define some variables:
p: Planet_Ref := Make_Planet;
hp: Habitable_Planet_Ref := Make_Habitable_Planet;
I would naively expect that assigning p := hp would work, because a Habitable_Planet is a subclass of Planet. But of course that won't work because every type defined with type is distinct and doesn't interoperate with any other type.
So I'd expect to have to declare Habitable_Planet_Ref to be a subtype of Planet_Ref to make this work. But the syntax doesn't seem to allow for this.
How do I make this work?
(Yes, I know I can use an explicit view conversion to cast a Habitable_Planet_Ref to a Planet_Ref, but that's really ugly and I'd like to avoid it.)
Ada recognizes types by name, so indeed you would need a view conversion here.
But if you are using Ada 2005, you can use anonymous access types instead. For instance:
hp: access Habitable_Planet'Class := Make_Habitable_Planet;
p: access Planet'Class := hp; -- valid with anonymous access types
One the drawbacks of using anonymous access types is that the code is more
verbose (although in general you would not use them for local variables, but
as parameters to subprograms or as fields in a (tagged) record.
They also can't be used with Unchecked_Deallocation. In fact, I personally often
use them exactly because of that: when I have a field in a record which is of an
anonymous access type, I know that the record does not "own" the accessed data,
and therefore it should not free it (in fact, I would have to write some convoluted
code to free them).
And of course as per your request the result for type matching are slightly more
relax, which is nice too.
ajb is correct in his comment. Ada is too strict for many practices you might be used to in other languages. An alternative would be to just not use objects and instead just simple records or discriminate records. I understand this may not be what you are looking for, but from my experience more can be done with less lines of code and the solution tends to me easier to understand.
Simple record
--...
type Rec_Planet is record
--.. stuff
end record;
--...
type Rec_Habitable_Planet is record
Planet : Rec_Planet := (others => <>);
--.. stuff
end record;
Discriminate record
type Enum_Planet is (Normal_Planet, Habitable_Planet);
type Rec_Planet(Kind : Enum_Planet := Normal_Planet) is record
-- rec_Planet stuff..
case Kind is
when Habitable_Planet => -- Rec_Habitable_Planet stuff
when others => null;
end case;
end record;
So #manuBriot gave me the answer I needed, but there were some other things I was doing wrong in my question which I should clarify because they'll confuse anyone else reading this question.
I was confusing the issue by using accesses. From Ada's point of view all accesses defined with type are distinct, so it never gets as far as looking at what the access is pointing at; it just disallows the assignment.
However, Ada does support implicit upcasting of class-wide types (and also discrete types, where an instance of a subtype will get implicitly cast to its parent type --- implement ALL the class hierarchies! But that's not really relevant here.) Example here:
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure Prog is
package Superclass is
type Class is tagged record
null;
end record;
procedure Announce(self: in out Class);
subtype Var is Class'class;
end;
package body Superclass is
procedure Announce(self: in out Class)
is
begin
Put_Line("I am the superclass");
end;
end;
package Subclass is
type Class is new Superclass.Class with null record;
procedure Announce(self: in out Class);
end;
package body Subclass is
procedure Announce(self: in out Class)
is
begin
Put_Line("I am the subclass");
end;
end;
osuper: Superclass.Class;
osub: Subclass.Class;
vsuper: Superclass.Var := osuper;
vsub: Superclass.Var := osub; -- implicit upclass here
begin
vsuper.Announce;
vsub.Announce;
end;
(It's in ideone here: http://ideone.com/M79l0a Interesting sidenote. If you define subtype Var is Superclass.Var in the Prog package, and then use Var in the definitions of vsuper and vsub, ideone's Ada compiler crashes.)
Of course, like all indefinite types, once the variable has been initialised then its type cannot be changed. So I can assign any Subclass.Object to vsub, but I can't assign a Superclass.Object to it. And of course I'm physically copying the object rather than referring to an object elsewhere.
Implicitly upcasting accesses to class-wide types should be safe. Because assigning to a class-wide type does a runtime instance check to make sure that the physical type of the objects are compatible, it ought not to be possible to accidentally corrupt objects like you can in C++ --- see Overwriting an instance of a subclass with an instance of a superclass, for example. Therefore assigning to a dereferenced access shouldn't be a problem. However, it's 2100 at night and my brain has turned to sludge, so it's entirely possible that I'm missing something here. (Although given that when using anonymous accesses there aren't any problems, I suspect not.) Elucidation welcome...

typeof Equivalent for Object Types in PL/SQL

I'm trying to use OOP and TDD inside of Oracle. Yes, I know that sounds crazy. And, I need some advice.
I'm writing a test for the following constructor method (simplified for the purposes of this question):
CONSTRUCTOR FUNCTION PERSON(p_pidm NUMBER, p_throw_exception NUMBER DEFAULT 0, p_program_id NUMBER DEFAULT 0)
RETURN SELF AS RESULT IS
BEGIN
-- Attach constructor parameters to internal attributes
self.throw_exception := p_throw_exception;
self.program_id := p_program_id;
-- TESTING STUDENT INSTANTIATION
self.student := NEW STUDENT(self.a_pidm);
RETURN;
END;
In the corresponding test, I'll need to verify that self.student is set to a valid instance of STUDENT. In other languages, I do this with a typeof method, but I'm not aware of one in PL/SQL.
So, the question is, does anyone know a function/procedure that I can pass a user-defined type into and get back its class/type name?
Thanks.
You probably want to use the IS OF <<type>> syntax.
Something like
IF l_variable IS OF( student )
THEN
<<do something>>
END IF;