General XMetaL Discussion
andygasser May 5, 2009 at 2:36 pm
What is selectedMay 5, 2009 at 2:36 pmParticipants 2Replies 3Last Activity 13 years, 5 months ago
I am new to XMetal programming and this seems like a simple question but I can't figure it out. I have a menu button and I need to be able to tell what is selected when the button is clicked. I can figure out what the container of the selected is, but not the selection itself. Is there any way to use the Range/Selection object to figure out what node(s) the user has selected?Derek Read May 5, 2009 at 9:39 pm
Reply to: What is selectedMay 5, 2009 at 9:39 pm
A few guesses based on what you have asked…
Selection.ContainerNode will give you the current node. At that point you can walk the DOM tree to find out the nodes within that node. This can be done various ways (and will need to be depending on what information you need). There is an example in the Programmers Guide called “Node example: A simple tree-walker” that might help, and you will also want to read the section called “Overview of the DOM interfaces”.
There is also the API called getNodesByXPath() that you might use to obtain a list of child elements within the current context.
It is also possible to use the Selection or Range APIs such as GotoNext(), MoveToElement(), MoveUp/Down/Left/Right(), SelectBeforeContainer(), etc, to do similar (but not really) operations as can be done using DOM calls. In some cases these can be easier to work with than the DOM and in some cases the DOM is more powerful. They are different however, with Selection and Range being tied more closely to what a user can select. The DOM is more abstract and for some people more difficult to get your head around.
If you need to know what 'type' of element the user is in you can use InContextOfType().
You might also wish to have a look at the journalist.mcr file which is part of the Journalist demo. It contains a lot of sample code, some of which you might be able to reuse.andygasser May 6, 2009 at 1:32 pm
Reply to: What is selectedMay 6, 2009 at 1:32 pm
It seems that it's not that simple. Selection.ContainerNode does not give you the current node, as the documentation states, it gives you the selection's container.
Consider this example:
When the user has the second Child element (child 2) selected how can I figure that out. When I use Selection.ContainerNode it returns the Parent element. Using DOM from there will allow me to navigate to the Child nodes but how do I know which one is selected.
I agree I can change the selection using the Selection API but how will it help me figure out which Child element is selected.Derek Read May 6, 2009 at 7:59 pm
Reply to: What is selectedMay 6, 2009 at 7:59 pm
Selection.ContainerNode does actually give you the current node. However, the definition of the current node as far as XMetaL is concerned is the element containing the current selection. When you select an entire element the containing node is actually that element's parent. This might be more apparent if you watch the “mini context” that is displayed at the bottom below the document. It is a list of elements like so: root / child1 / child2 / etc... It might also be more clear if you have the Element List open with the Insert radio button selected and then make various selections. If you have the Attribute Inspector open it also displays what XMetaL considers to be the container node at the top (as the default, you have the option to select and set attributes for ancestors as well).
However, I think I understand your issue as some people customizing the product wish to try to “fix” the idea of how XMetaL treats selections and insertion points for their users. You can either write your script assuming your users know how XMetaL treats selections or you can try to “fix” it. However, keep in mind that if you fix this you may introduce further confusion for any users that use the “mini context” to navigate or the Element List to insert elements or the Attribute Inspector to set attribute values.
There are various other APIs that might help here, but you'll need to figure out which because I'm not sure what the final goal is. I think you might experiment with Selection.IsInsertionPoint to figure out if the user has anything selected (anything from a single character up to an entire element returns false). You might then set a Range and try to move it into what you consider to be the correct position by calling Range.Collapse() and then move the Range around. Or perhaps you could store the current Range in a variable, call Range.SelectElement(); and store that in a second variable, then compare the two using IsEqual. If they are different you might assume the “correct” element is actually the ContainerNode of the first Range.
- You must be logged in to reply to this topic.