Prompt user to answer boolean choice using Revit API in C# - c#

I created a Revit plugin in C# that allow users totally new to 3D technology to choose a family, and insert it in their project. But right now the user does not have the choice between placing an object on the point anywhere or on a face. It's either one or the other.
Right now my code looks like this :
bool useSimpleInsertionPoint = false; //or true
bool useFaceReference = true; //or false
if (useSimpleInsertionPoint)
{
//my code for insertion on point here
}
if (useFaceReference)
{
//my code for face insertion here
}
What I would like to do is ask the user what does he want to do.
Does TaskDialog.Show would do the trick or is it something else ?
Thanks in advance.

Vincent's approach is good. The one thing that I like a little bit more is to use the CommandLink options with TaskDialog. This gives you the "big option" buttons to pick from, provides both an answer as well as an optional line of "explanation" about each answer.
The code looks like:
TaskDialog td = new TaskDialog("Decision");
td.MainContent = "What do you want to do?";
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink1,
"Use Simple Insertion Point",
"This option works for free-floating items");
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink2,
"Use Face Reference",
"Use this option to place the family on a wall or other surface");
switch (td.Show())
{
case TaskDialogResult.CommandLink1:
// do the simple stuff
break;
case TaskDialogResult.CommandLink2:
// do the face reference
break;
default:
// handle any other case.
break;
}

This should do the trick:
TaskDialog dialog = new TaskDialog("Decision");
dialog.MainContent = "What do you want to do?";
dialog.AllowCancellation = true;
dialog.CommonButtons = TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No;
TaskDialogResult result = dialog.Show();
if(result == TaskDialogResult.Yes){
// Yes
TaskDialog.Show("yes", "YES!!");
}
else
{
// No
TaskDialog.Show("no", "NO!!");
}
Code tested and proved to work in a Revit macro in 2014 so should work fine anywhere else in an add-in as well.

Related

Cannot interact an element because Windows Inspect cannot show that element in question - WinAppDriver + Selenium?

I need an advise from those who have more experience on automating a window desktop application.
I cannot automate a test in a certain form because I believe it cannot be done as Win Inspect cannot really see them. I will show you 2 images below what I meant by this.
this image is an example where I CAN automate the button Close using the following BDD, because Win Inspect can see it.
Scenario Outline: IP120929-00060 - I Check Button
Then Button "Close" Is Displayed
the image below is an example where I CANNOT automate the button Close using the same BDD & test definition (and method), because (I believe) Win Inspect cannot see it (however the properties of that element in question can be viewed)
Scenario Outline: IP99999_DEL_ME-00099 - I Check Button
Then Button "Close" Is Displayed
The Test Definition/Binding for that BDD is:
[Then(#"Button ""(.*)"" Is Displayed")]
public void ThenButtonIsDisplayed(string button)
{
var proc = $"Then Button {button} Is Displayed";
if (CombinedSteps.OutPutProc(proc, OutputLevel.Then))
{
if (Helpers.Button.**Displayed**(button, 3))
{
CombinedSteps.Success();
return;
}
}
CombinedSteps.Failure(proc);
}
public bool **Displayed**(string button, int timeout = 3, string windowName = "")
{
DebugOutput.Log($"Proc - Displayed {button} {timeout} '{windowName}' CurrentPage = {CurrentPage.ToString()}", OutputLevel.Procedure);
if (windowName != "")
{
DebugOutput.Log($"We need to narrow down by window");
return DisplayedByWindow(button, windowName, timeout);
}
var buttonId = CurrentPage.GetElement(button);
if (buttonId == null)
{
DebugOutput.Log($"Did not find a mention of that element in forms Element Factory, ");
return false;
}
var buttonLocator = buttonId.Locator;
DebugOutput.Log($"Find Element by {buttonLocator} ");
if (!JustOneButtonToPress(buttonLocator))
{
var currentPageName = CurrentPage.Name.ToLower();
currentPageName = currentPageName.Replace(" page", "");
var buttonInWindowElement = GetButtonElementInWindow(currentPageName, button);
if (buttonInWindowElement == null)
{
DebugOutput.Log($"Even in window I'm failing to find {button} {currentPageName}");
return false;
}
DebugOutput.Log($"Found in the window - it will click the first that fits under the window");
return buttonInWindowElement.Displayed;
}
DebugOutput.Log($"Got the locator of {buttonLocator}");
var buttonElement = SeleniumUtilities.GetElement(CurrentPage.GetElement(button).Locator, timeout);
if (buttonElement == null)
{
DebugOutput.Log($"Did not find a mention of that element in form");
return false;
}
DebugOutput.Log($"It exists {buttonElement}");
return buttonElement.Displayed;
}
the code will always return buttonElement as null for the Create Curves window form
Its frustrating thing trying to make this works, so my question to know better and have more experience, is this a limitation of the Desktop Application I am testing or is there another way around this? Is it better to ask the Developer to change something about it in the Application?
I have tried to map the 'Close' button in question using it's ID, Name and/or XPath - but all to no avail
any guidance on this would be much appreciated.
Cheers.

FastColoredTextbox AutoWordSelection?

FastColoredTextbox is an user-control that can be downloaded in this url, it looks like this:
Its an amazing control but only can select one word when doubleclicking on the text, can't hold the mouse to select more words, so it only selects the entire current word over the mouse pointer even if you try to move the mouse cursor to left or right to select more text.
I have not found any information explaining the problem, and all of the official example projects has this problem.
Nobody means how to make an AutoWordSelection equivalent of a default TextBox for a FastcoloredTextbox control, but even the most important thing is:
How to select just more than one word with the mouse?
UPDATE:
#mostruash answer is very instructive but in all this time I could not carry out the modifications by myself.
I need a huge help from a C# programmer to carry out this task, my knowledge of C# is very low and the modifications that I made to the source did not work (don't compiled), I went back to the original user-control source to not end up spoiling more. I hate to say this but this time I need the job done, this source is too much for me.
If I'm requesting for too much then maybe with the necesary extended instructions of a C# developer, explaining how to accomplish this step by step, maybe I could carry it out by myself.
UPDATE
A video that demostrates the problem:
https://www.youtube.com/watch?v=Cs2Sh2tMvII
UPDATE
Another demo, I show what the FastColoredTextBox can't do but I would like to do like every other text-editor can do:
I've checked the source code of the project. Dragging is cancelled if a double click occurs and SelectWord is called.
You could modify the source code to include the feature that you request. (https://github.com/PavelTorgashov/FastColoredTextBox). In that case:
You must trace selections that start with double clicks.
Instead of calling SelectWord function, use the Selection class and draggedRange attribute to mark the selected word in OnMouseMove.
You also must handle deselection of words in OnMouseMove.
You must also select spaces between words in OnMouseMove.
The double click is handled in the code piece below:
if (!isLineSelect)
{
var p = PointToPlace(e.Location);
if (e.Clicks == 2)
{
mouseIsDrag = false; //Here, drag is cancelled.
mouseIsDragDrop = false;
draggedRange = null; //Drag range is nullified
SelectWord(p); //SelectWord is called to mark the word
return;
}
if (Selection.IsEmpty || !Selection.Contains(p) || this[p.iLine].Count <= p.iChar || ReadOnly)
OnMouseClickText(e);
else
{
mouseIsDragDrop = true;
mouseIsDrag = false;
}
}
EDIT:
This may require a lot of work to accomplish. So maybe you should use another tool/library. I have not studied the whole source code so there will probably be additional steps to those provided above.
For example, to trace double clicks you can do the following:
Define a class variable/property in FastColoredTextbox.cs: bool isDoubleClick.
Set it to true in OnMouseDown under if(e.Clicks == 2) condition. Set it to false in all other conditions.
Set it to false in OnMouseClick or OnMouseUp or in other relevant mouse event handlers.
That way you will know if series of mouse events had started with a double click event or not. Then you would act accordingly in OnMouseMove because that is where you (un)mark characters or (un)mark words.
LAST WORDS OF CAUTION:
The author of that project did not include any inline comments or any other means of documentation so you will be studying the code line by line to understand what each function/part does.
Add the following statement between Line 5276 and line 5277 in the class FastColoredTextBox.cs:
SelectWord(p);
mouseIsDrag = true; // here
return;
Note that implementing the ultimate behavior would require a good bunch of coding. Whereas the workaround mentioned above might satisfy your needs.
As #mostruash points out in his answer, that is the place where author cancels the mouse drag. Not sure why he deliberately prevents this feature. Only he knows.
if (e.Clicks == 2)//Line 5270
{
mouseIsDrag = false;
mouseIsDragDrop = false;
draggedRange = null;
SelectWord(p);
return;
}
I didn't read whole code, and I have no reason to do it. I just checked quickly and removed them. And it works as you expect.
if (e.Clicks == 2)//Line 5270
{
//Comment or remove completely.
//mouseIsDrag = false;
//mouseIsDragDrop = false;
//draggedRange = null;
SelectWord(p);
return;
}
Note: Am not sure this breaks something else, I've not tested. At least that works. Test it yourself.
My solution is a bit tweaky, but seems to work at first glance.
You have to make some changes in the Code:
Add mouseIsWholeWordSelection flag and a Range variable which can store the initial selected range after double click (best after line 100, I guess):
private bool mouseIsWholeWordSelection;
private Range mouseIsWholeWordSelectionBaseRange;
Change the selection code for double click event as stated above and extend it a bit (line 5222):
if (e.Clicks == 2)
{
//mouseIsDrag = false;
mouseIsDragDrop = false;
mouseIsWholeWordSelection = true;
//draggedRange = null;
SelectWord(p);
mouseIsWholeWordSelectionBaseRange = Selection.Clone();
return;
}
Add evaluation of dragging event for recreating selection (line 5566):
else if (place != Selection.Start)
{
if (mouseIsWholeWordSelection)
{
Selection.BeginUpdate();
var oldSelection = Selection.Clone();
SelectWord(place);
if (Selection.End >= mouseIsWholeWordSelectionBaseRange.End)
{
Selection.Start = (mouseIsWholeWordSelectionBaseRange.Start > Selection.Start) ? mouseIsWholeWordSelectionBaseRange.Start : Selection.Start;
Selection.End = mouseIsWholeWordSelectionBaseRange.End;
}
else if (Selection.Start < mouseIsWholeWordSelectionBaseRange.End)
{
Selection.Start = new Place(Selection.End.iChar, Selection.End.iLine);
Selection.End = mouseIsWholeWordSelectionBaseRange.Start;
}
Selection.EndUpdate();
DoCaretVisible();
Invalidate();
}
else
{
Place oldEnd = Selection.End;
Selection.BeginUpdate();
if (Selection.ColumnSelectionMode)
{
Selection.Start = place;
Selection.ColumnSelectionMode = true;
}
else
Selection.Start = place;
Selection.End = oldEnd;
Selection.EndUpdate();
DoCaretVisible();
Invalidate();
}
return;
}
Add at every place where isMouseDrag is being set to false:
isMouseWholeWordSelection = false;
And there you go.

Detecting input consisting of just spaces

I have a wepage for a user to sign up,i have tested it and runned it,i was testing it using space not entering any words to signup,meaning a user can signup without entering any words just by using space.so i dont want this to happen to my webpage.
any one who has some code that i can use to validate this...
You can use the method: string.IsNullOrWhiteSpace to check
either the simple string.IsNullOrWhiteSpace
or if you really want to use the answer you chose, you should edit it to:
if (firstName ! = null && lastName ! = null)
{
if (firstName.Trim()=="" || lastName.Trim()=="")
{
return False;
}
else
{
return True;
}
}
else return False;
you can validate user input in many ways. One of them is to use built in Visual Studio Vaidator controls and make sure that each control is tighed to a text box in your form and its preoperty is selected to ensure the field is filled before submitting the form.
Another way is to do the validation from the code behind. Something like this:
if (firstName.Trim()=="" || lastName.Trim()=="")
{
return False;
}
else
{
return True;
}

Reducing code redundancy in C#

I'm new to tinkering with C#, and so far that's the extent of it. I'm just tinkering for a small project I have.
The redundancy is driving me crazy, though. Writing long lists of similar code taking up line after line just doesn't sit well with me.
I have a few tabs with checkboxes and radio buttons in them, that's where I noticed the duplication the most. Unfortunately I... don't quite grasp every aspect of C# as well as I should, yet. So I was hoping to learn from you folks.
Example:
//setup checkbox
checkBox1.AutoSize = true;
checkBox1.Checked = false;
checkBox1.CheckState = CheckState.Unchecked;
checkBox1.Location = new Point(5, 102);
checkBox1.Text = "Check Box 1!";
checkBox1.UseVisualStyleBackColor = true;
//set radio 1
radio1.AutoSize = true;
radio1.Checked = true;
radio1.Location = new Point(5, 33);
radio1.Size = new Size(20, 20);
radio1.Text = "Radio-e-o-e-o";
radio1.UseVisualStyleBackColor = true;
//set radio 2
radio2.AutoSize = true;
radio2.Checked = false;
radio2.Location = new Point(5, 56);
radio2.Size = new Size(18, 20);
radio2.Text = "Option 2!";
radio2.UseVisualStyleBackColor = true;
My instinct would be to set up some arrays with the variable data for things like the names and the distinct data. But as I said, I'm very new, I've only been tinkering... and the resources I've come across tend to either not match what I'm looking for, or add layers of complexity I'm probably not ready for.
If I got your question right: you can make a method:
private CheckBox DoSomethingWith(CheckBox checkBox, Point location, string text)
{
checkBox.AutoSize = true;
checkBox.Checked = false;
checkBox.CheckState = CheckState.Unchecked;
checkBox.Location = location;
checkBox.Text = text;
checkBox.UseVisualStyleBackColor = true;
return checkBox;
}
then pass a checkbox to it checkBox1 = DoSomethingWith(checkBox1, new Point(10,10), "My Text");
You can make your own class that inherits from RadioButton, set your default settings, and use it.
public class MyRadioButton : public RadioButton
{
MyRadioButton()
{
UseVisualStyleBackColor = true;
AutoSize = true;
}
}
Then you just add this control instead of RadioButton.
So...you want to refactor the Form1.designer.cs file?
Anything you do to "clean up" would place an unnecessary burden on the CPU just for the sake of "clean code". Just let the designer be (unless you're talking repeat designs, in which case a user control may be the way to go).
Those are my impressions on this, anyways
If all you're trying to do is tinker, and not set up a whole application architecture, and you're writing this yourself rather than trying to mess w/ the designer-generated code, then using some kind of structure you can loop over is probably you're best option. LINQ has some really nicer operators for doing simple transformations like that.
For example,
var formElements = myArrayofElementInfo.Select(e => CheckBox(e.Point, e.Text))
That also assumes you're using something like the CheckBox method presented by #Sean87 to consolidate construction.
Maybe you could reduce the redundancy by creating methods to initialize your controls passing the controls as parameters (you could also create the control inside the method itself). For example:
public void setupCheckbox (Checkbox checkbox, boolean autoSize, boolean checked, etc.)
public void setupRadioButton (RadioButton radiobutton, boolean autoSize, boolean checked, etc.)
And then create the controls using the above methods:
setupCheckbox (checkBox1, true, false, etc.)
setupRadioButton (radio1, true, false, etc)
setupRadioButton (radio2, true, false, etc)
Anyhow, the visual attributes of the classes you are referring to normally are defined within the IDE (e.g. Visual Studio) so normally you don't care about them. Maybe you could consider storing the Text in an array for the initialization of the different controls if you find it useful.

Create a VS2010 Addin to collapse every methods of my active document

I'm looking for the source code to collapse every methods of my active document using the VS2010 Addin.
For the moment I parse the text content of the document trying to match if the line is a method signature. If it is the case, I collapse the method.
TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;
var editPoint = selection.ActivePoint.CreateEditPoint();
editPoint.MoveToLineAndOffset(1, 1);
while (!editPoint.AtEndOfDocument)
{
editPoint.StartOfLine();
var line = editPoint.GetText(editPoint.LineLength).TrimStart();
if (line.StartsWith("public"))
{
selection.MoveToLineAndOffset(editPoint.Line, 1);
_applicationObject.ExecuteCommand("Edit.ToggleOutliningExpansion");
}
// go to the next line
}
Does anyone could tell me if I'm on the good way or if there is an easiest way ?
Maybe I asked not so well my question. My real goal was to collapse all the code : properties, methods, comments with ///, using; but not the regions.
Here is one solution :
// reduce everything like Ctrl+M+O
_applicationObject.ExecuteCommand("Edit.CollapsetoDefinitions");
// save the cursor position
TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;
var selectedLine = selection.ActivePoint.Line;
var selectedColumn = selection.ActivePoint.DisplayColumn;
// open the regions
selection.StartOfDocument();
while (selection.FindText("#region", (int)vsFindOptions.vsFindOptionsMatchInHiddenText))
{
// do nothing since FindText automatically expands any found #region
}
// put back the cursor at its original position
selection.MoveToDisplayColumn(selectedLine, selectedColumn);
I hope this could help

Categories

Resources