Refer to this prior question/answer combo of mine. It's describing how to create a property editor for the IDE.
I've created another property editor for a completely different purpose. In this case, it's a glyph character selector of type String (because it could contain more than one glyph character). Unlike my other one in mentioned question/answer, this one is very specific to a particular property on a particular TCollectionItem class of mine.
All is good, and I can invoke this property editor for this particular property. However, I have a dilemma. The property editor, by nature, is directly related to a font. The user may choose a character (glyph) from a particular font. My property editor has the facility to change the font, and browse the glyphs contained within that font.
This component of mine also has the facility to specify the font, in a separate TFont property. The problem arises when it comes to the combination of both my Glyph property and Font property being used in the very same property editor. When I invoke this editor for the Glyph property, it also needs to know the Font which it needs to use. On the contrary, when user chooses a font and glyph character in this editor, it also needs to update both the Glyph and Font properties.
Long story short, PropertyB depends on PropertyA. If PropertyA changes, then PropertyB will have an entirely different set of possible values. So, whatever editor I install in the IDE needs to allow the user to change both PropertyA and PropertyB at the same time.
How can I make a property editor have access to more than one property?
TPropertyEditor has a public GetComponent() method that you can use to access the object(s) whose property is currently being edited (multiple objects with the same property can be edited at the same time, if the property editor allows it). Then you will have access to all of the other properties in the same object(s).
That being said, if your editor displays a pop-up dialog for editing, it should be implemented as a component editor instead of (or in addition to) a property editor. A property editor should edit only one property at a time, though it may have read-only dependancies on other properties. For instance, a Glyph property editor that also edits the Font property, and vice versa, is not a good design. But a component editor that edits both is perfectly acceptable.
Solution 1
Instead of a property editor, implement a component editor. Such a component editor will have access to the entire component, not just a single property.
Solution 2
Wrap both of your properties inside of a dedicated TPersistent class, and then create a TClassProperty property editor for this class instead. The individual properties will not actually invoke a property editor. Instead, their parent TPersistent will invoke a combined property editor which has access to all the properties within this class. A good existing example is the TFont editor.
Related
I've read that the most centralized way to have font-consistency through a project is to have all controls with the ParentFont property active and set the Application.DefaultFont at runtime.
I would like to apply a different font, say 'Segoe UI', in the whole application at design time.
How can it be changed at design time?
You have a number of options, what works best for you may depend on your situation.
If you are using your own forms (not from a package or library) then you can design each to inherit from a parent to give you a starting font as suggested in the comments. However the IDE will allow this to be changed, and if the DFM file for the form records a font in the derived form, it will use that font even if the parent class font is changed.
Another approach would be to write a non-visual component that you can drop onto a form. When that component has it's Owner set (at creation) it can check if it is owned by a Form and set the font on the parent. In the same way it can set any properties you want it to, and it can also find the children of it's owner and set any properties on those controls as well.
Moving on from this you could, at runtime, look at the TScreen class which contains properties called CustomForms and Forms which allow you to access all currently active descendents of TCustomForm and TForm respectively. As you can access this you could change the fonts on all of them at runtime. So if you allow your user to select a font, using the Screen object you can change the font on all forms.
The combination of the two can allow you to easily gain control over display properties.
Be aware that changing the font face can change the size of the text rendered. (As of course will changing the font size and style). This can affect how your controls look and the alignment of them.
In the Delphi IDE, some components in Delphi have the ability to "add" properties to the child controls they contain in the property editor.
How can I achieve the same thing with my own TCustomPanel descendant?
Some more details:
What I want to achieve is the following: I have a very complex configuration dialog for an application with a large number of visual components.
I want to add to each of these components a "complexity index" (an integer) that will be used to show or hide the component based on a selection made by the user (a dropdown with "simple", "advanced" and "expert" options).
I understand that the property will actually belong to the parent panel but I need a way to display it, in the IDE, as if it was attached to the control it is related to.
The perfect exemples are the various "organizational" panels provided by Delphi: TGridPanel and TRelativePanel. Each of these have a ControlCollection (published) properties that is used to hold the actual states of the additional properties but I failed to locate how the property editor knows that it must attach the properties to the child controls.
Here is a screenshot of a TLabel placed inside a TRelativePanel with the relevant properties highlighted:
I've noticed that some properties disappear from the Object Inspector when selecting more than one item.
Why does this happen and how to control this behavior when creating a component?
Example:
Add 2 buttons (TButton) to a form and select one of them.
In the Object Inspector you can see all TButton's published properties (Note that there's also the Constraints property).
Add the other button to the current selection (Click while pressing Shift key).
As you can see, some properties have been hidden from Object Inspector (Note that the Constraints is no more visible).
Whether a property is displayed when multiple objects are selected is controlled by the property editor configured for that property. Property editors (descended from TPropertyEditor in DesignEditors.pas) have a GetAttributes method that returns a set of attributes that apply to the editor. If the set includes paMultiSelect, then the property will be displayed.
Given that the property value is displayed as the constraint values, rather than just (TSizeConstraints), I conclude that that property is not using the generic TClassProperty editor. That editor sets paMultiSelect, but based on your pictures, the property editor to TSizeConstraints doesn't. It was probably an oversight.
You could try registering your own property editor. Find the property editor currently registered for TSizeConstraints (by searching the source code for TSizeConstraints, for instance) and, in a design-time package, declare a new class descended from that one. Override GetAttributes to return the value you need. Finally, follow examples elsewhere in the code to call RegisterPropertyEditor.
I bought the TMS Component pack and want to hide some component properties from displaying in the object inspector.
I am using UnlistPublishedProperty to hide them.
It works most of the time. But for some reason e.g. Anchors or StyleSettings are still displayed.
I am calling it like this:
UnlistPublishedProperty(TAdvEdit, 'StyleElements');
The weird thing is that it works on 90% of properties and i can't figure out why it will not hide the other properties from the object inspector.
I could edit the source and comment out the line where it gets published from TCustomEdit but i am wondering why the method with UnlistPublishedProperty isn't working.
Thanks!
The properties you are trying to remove are inherited from a higher ancestor class. If you wish to use UnlistPublishedProperty to remove these particular properties, you'll have to remove them from the ancestor. However, that would apply to all controls, not just the one you're working on.
In addition to Jerry's answer; there is a solution for deleting properties from sub-components. The third part of my answer here demonstrates how to filter out properties of a sub-component of a custom component by registering a component PropertyEditor and overriding GetProperties to filter specific property names.
I have my own visual component. It has many published properties and events. I want them to be shown in the specified standard categories of Object Inspector at design-time (Visual, Layout, Drag Drop / Docking, Linkage etc).
Now all my properties are in the Miscellaneous category.
You can use RegisterPropertyInCategory function, defined in the DesignIntf. Example.