Custom editor in MPS - dsl

I have an concept in Jetbrains MPS which I would like to create a custom editor for.
The concept have a number of children.
For each child I would like to display the child's own editor but with a "-" in front of it.
I'm not completely sure I'm trying to solve this in the right way.
But my first attempt is a custom cell looping over the child nodes.
My problem is that I can't figure out how to find the editor cell of the child nodes:
My cell provider:
return new AbstractCellProvider(node) {
#Override
public EditorCell createEditorCell(EditorContext ctx) {
EditorCell_Collection cells = EditorCell_Collection.createVertical(ctx, node);
foreach n in node.elements {
EditorCell_Collection a = EditorCell_Collection.createHorizontal(ctx, node);
EditorCell_Label label = new EditorCell_Constant(ctx, node, "-");
a.addEditorCell(label);
cells.addEditorCell(a);
how to add the child node's editor here?
}
return cells;
}

What are you really trying to achieve? An example might help here...
Without further context (so I may misunderstand your problem), I think you could use an EditorComponent (https://www.jetbrains.com/help/mps/editor.html#editorcomponentsandeditorcomponentcells) for the original editor and then make an editor with a "-" constant followed by the EditorComponent to achieve the desired effect.

Related

Selection, Sorting and Highlighting Elements in the selected order using PickObjects() method (Revit API)

Is there a method Revit API where I can select elements in order, highlighting the elements selection.
Please note, Selection.PickObjects() does the selection & highlighting but does not save the elements in the order of Selection.
It is exactly as you say. No, the Revit API does not provide a built-in method providing the functionality you require. You can implement it yourself by calling PickObject repeatedly in a loop and collecting the selected elements in your own sorted list.
The easiest way you can fix your problem is by using the following method.
public List<Element> GetElementsBySelection(UIDocument uiDoc)
{
bool flag = true;
List<Element> listElem = new List<Element>();
do
{
try
{
Reference referencia = uiDoc.Selection.PickObject(ObjectType.Element);
Element elem = uiDoc.Document.GetElement(referencia);
listElem.Add(elem);
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException e)
{
flag = false;
}
} while (flag);
return listElem;
}
This method ends when you press the "Esc" key. Other more elegant ways to detect when the key is pressed were discussed in the following forums: Monitoring keyboard and Detect key press.
I hope that it serves as a guide so that you can continue advancing in the development. Best regards.
Thanks to Jeremy Tammik for the general idea to solve the problem.

Class extending AbstractDetailsDescriptionPresenter text gets cut off

I'm using a class extending AbstractDetailsDescriptionPresenter. The summary text is relatively long. For some reason the text gets cut off after a certain length. I could not figure out how to display the entire text without it being cut off.
I tried viewHolder.getBody().setLines(20); and other property changes but nothing seemed to have the desired effect.
This it the Presenter class I'm using:
public class MovieDetailPresenter extends AbstractDetailsDescriptionPresenter {
#Override
protected void onBindDescription(ViewHolder viewHolder, Object item) {
Video video = (Video) item;
if (video != null) {
viewHolder.getTitle().setText(video.title);
viewHolder.getSubtitle().setText(video.subtitle);
viewHolder.getBody().setText(video.summary);
}
}
}
How can I remove the text length limit/cutting off?
Here a picture to better illustrate what I mean. The text at the bottom right isn't displayed in its full length but gets cut off and adds three dots (...) at the end.
Thanks for any hints/help.
Finally found a solution: Making a custom “AbstractDetailsDescriptionPresenter” without the addPreDrawListener() method (which is causing the problem) and use it in the “DetailsDescriptionPresenter”.
body.setMaxLines(Integer.MAX_VALUE) should do the trick unless you are forcing a specific height somewhere in your LayoutParams. I assume you're setting height to wrap_content? You could try enabling Show Layout Bounds in the developer options to see if your changes have any effect.

Styling NSOutlineView Rows

I have a Document based Core Data app with an NSTreeController supplying the content to a view based NSOutlineView. I am "styling" (setting text colour, background colour etc.) the rows based on persistent "transformable" NSColor and NSFont attributes in my data model which the end use can modify. When a new row is popped up, it displays things with the colours/fonts set in the data model. Here is the delegate/datasource code that sets the row background colour:
- (void) outlineView:(NSOutlineView *)outlineView
didAddRowView:(NSTableRowView *)rowView
forRow:(NSInteger)row
{
// Get the relevant nodeType which contains the attributes
QVItem *aNode = [[outlineView itemAtRow:row] representedObject];
if (aNode.backColor)
{
rowView.backgroundColor = aNode.backColor;
}
}
However when the style attributes change I want the associated visible rows to be redrawn with the new style values. Each time a "style" attribute is changed, I am using NSNotificationCenter to send a notification to the Outline view delegate, with the model object whose row needs to be redrawn with the changed style. This is the code in the delegate that receives the notification.
-(void) styleHasChanged: (NSNotification *)aNotification
{
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:aNotification.object];
[myOutlineView reloadItem:aTreeNode];
}
My assumption here is that I can navigate the tree controller to find the tree node which is representing my model object and then ask the outline view to redraw the row for that tree node. This is the "additions" code in the tree controller which walks the tree to find the object - not super efficient, but I don't think there is another way.
#implementation NSTreeController (QVAdditions)
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject
{
return [self treeNodeForModelObject:aModelObject inNodes:[[self arrangedObjects] childNodes]];
}
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject inNodes:(NSArray*)nodes
{
for(NSTreeNode* node in nodes)
{
if([node representedObject] == aModelObject)
return node;
if([[node childNodes] count])
{
NSTreeNode * treeNode = [self treeNodeForModelObject:aModelObject inNodes:[node childNodes]];
return treeNode;
}
}
return nil;
}
So sometimes this works and the row redraws, and sometimes it doesn't. The delegate method "styleHasChanged:" is always called, and the tree controller always returns a corresponding tree node (Actually of a subclass of NSTreeNode). But more often than not the outline view does not recognise the tree node, and the row is not redrawn. Its like the tree controller has given back a different tree node object to the one it gave the outline view in the past. But weirdly sometimes it does work and the right row is redrawn with the new background colour. If I collapse the row out of view and pop it open again, it is redrawn correctly.
Anyone any idea why it works sometimes and not other times?
It would be nice to be able to bind the colour/font attributes to the row and columns in some way, so that the outline view did this styling automatically with KVO, but I don't think that is possible - is it?
You spend hours/days trying to work out what you've done wrong; You write the question out; Post it; Sleep on it; and think how stupid can you be.
So I asked the NSTableRowView to redraw itself, but I had not set the new background colour. So here is the new improved (and works) version of styleHasChanged:
-(void) styleHasChanged: (NSNotification *)aNotification
{
QVItem *modelItem = aNotification.object;
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:modelItem];
NSInteger rowIndex = [myOutlineView rowForItem:aTreeNode];
if !(rowIndex == -1)
{
NSTableRowView *rowViewToBeUpdated = [myOutlineView rowViewAtRow:rowIndex makeIfNecessary:YES];
rowViewToBeUpdated.backgroundColor = modelItem.backColor;
}
}
Duh!

Monotouch Dialog: Styling Elements

I'm using Dialog and would like to style all my cells. I have a background image, and in the samples I can see how you can use a StyledStringElement to use that image.
However, in real use some sections use other elements. For example the last element in one section is a RootElement - but it has no BackgroundUri property to set. The same would go for boolean elements.
I found this question - What's the best way to customise all monotouch.dialog TableViewCells to the same style (Background, etc..)? which is a similar question a year and a half back. The UIAppearance styling mentioned does exist for tablecells but does not work with MTDialog. krtrego's answer to this In monotouch.dialog can RootElement be easily styled? question purports to do the job, but no styling occurred when I implemented it.
Is there now any improved way to do this? Implementing my own 'styled' versions of these other control types would be a big effort and looking at the styledstringelement this is beyond my current skill level.
Here's an example of what I'd like to achieve (the shadow below the 'tags' cell, but the element is actually a RootElement with a set of radio options beneath it). Removing the default grey lines etc is easy enough, but putting a subtle shadow on the bottom cell of each section is what I cannot work out.
Many thanks!
PS. With a normal MTDialog screen with cell backgrounds and borders removed, there is a subtle white shadow/line beneath each section as it is. If I could just recolour that I'd be a long way to where I want to be...
Subclassing the element will let you style it via overriding the GetCell method, but that gets pretty tedious. The best solution I have come across is to to make a custom DialogViewController by subclassing it, and overriding the CreateSizingSource method with your own SizingSource and GetCell() methods using the images you want for each scenario of a cell (top, middle, bottom, alone). Its a bit of code and my example wont handle uneven rows, but it is the only solution I have seen that does not modify the MT.D source code.
Here is what you would override in your DialogViewController subclass:
public override Source CreateSizingSource(bool unevenRows)
{
return new CustomSource(unevenRows);
}
Then you would make a custom source class:
public class CustomSource : Source
{
public CustomSource(DialogViewController parent) : base (parent)
{
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var theCell = base.GetCell(tableView, indexPath);
if (RowsInSection(tableView, indexPath.Section) == 1) //use one with top and bottom rounded
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundFull);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundFullActive);
} else if (indexPath.Row == 0) //top only
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundTop);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundTopActive);
} else if (indexPath.Row+1 == RowsInSection(tableView, indexPath.Section)) // bottom only
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundBottom);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundBottomActive);
} else //anything in the middle
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundMiddle);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundMiddleActive);
}
return theCell;
}
}
Theme is just a static class that returns UIImages, similar to the example Field Service app from Xamarin. So here I have made 8 images total. 4 to represent the top, middle, bottom and alone for an element. Each has different rounded corners to appear correct. And then a "highlighted" version of each for when its touched.
The big drawback here is you have to do this for every different styled controller you would need. If you are ok with modifying the MT.D source code, you can get a different solution that will allow you to control it at the Section level here: http://fastchicken.co.nz/2012/05/20/earnest-debrief-visual-styles-in-ios-apps-uiappearence-custom-sections-in-monotouch-dialog/
Which has the same effect, but you only need to subclass Section for each different style, which makes including multiple styles in one Root easier. A pull request was made for this change, but Miguel favored the first solution instead, seen here: https://github.com/migueldeicaza/MonoTouch.Dialog/pull/180

Is there a way to change the text of checked/unchecked MCheckBox states?

How would I go about changing the default MCheckBox state text (currently I/0) to, for example, YES/NO or ON/OFF?
Mr. Daniel Kurka is the author for all the widget classes in MGWT. If the look & feel is not
fulfilling our requirement, We can edit those classes and rewrite them according to our requirement.Because they are open source. I done this on many classes like CellList,FormListEntry and MCheckBox. code for ON/OFF instead of I/O
public MyOwnCheckBox(CheckBoxCss css) {
this.css = css;
css.ensureInjected();
setElement(DOM.createDiv());
addStyleName(css.checkBox());
onDiv = DOM.createDiv();
onDiv.setClassName(css.on());
onDiv.setInnerText("ON");
getElement().appendChild(onDiv);
middleDiv = DOM.createDiv();
middleDiv.setClassName(css.middle());
Element middleContent = DOM.createDiv();
middleContent.setClassName(css.content());
middleDiv.appendChild(middleContent);
getElement().appendChild(middleDiv);
offDiv = DOM.createDiv();
offDiv.setClassName(css.off());
offDiv.setInnerText("OFF");
getElement().appendChild(offDiv);
addTouchHandler(new TouchHandlerImplementation());
setValue(true, false);
}
Write a new class like MyOwnCheckBox.just copy the code in MCheckBox and paste in your class MyOwnCheckBox, find and replace the MCheckBox with MyOwnCheckBox in the code(change constructor's name). do the following changes.
onDiv.setInnerText("ON");
offDiv.setInnerText("OFF");
and finally create object to MyOwnCheckBox rather MCheckBox, it'll shows MCheckBox with ON/OFF.
Right now there is no way to do that, but there is no real reasons that checkbox does not implement HasText other than we might need to update the css so that big text will not break the layout.
If you think mgwt should implement this go and vote for this issue: http://code.google.com/p/mgwt/issues/detail?id=171
Well, an easy way to accomplish the same thing, without creating a new class that mimics MCheckBox, is to do something like the code below:
CheckBoxCss css = MGWTStyle.getTheme().getMGWTClientBundle().getCheckBoxCss();
String offClass = css.off();
String onClass = css.on();
NodeList<Node> checkBoxElems;
mIsSingleSkuBox = new MCheckBox(css);
checkBoxElems = mIsSingleSkuBox.getElement().getChildNodes();
for( int i = 0; i < checkBoxElems.getLength(); i++ )
{
Element openElem = (Element) checkBoxElems.getItem(i);
String className = openElem.getClassName();
if( className.equals( offClass))
{
openElem.setInnerText("No" );
}
else if( className.equals( onClass))
{
openElem.setInnerText("Yes" );
}
}
It will probably have space problems with anything longer than 3 characters, but it works consistently with "Yes" and "No" for me.

Resources