Disabling Save Button when Validation Errors Occur In An Eclipse-RAP Application - eclipse-emf

We are using Eclipse API in our RAP application.This uses Eclipse Modeling Frame Work.
When a page gets edited, Model Becomes Dirty and as a Result,Save Button gets Enabled.
In our editor pages, when ever there is an error in the Page, we set the Validation flag of the Editor page to false, which would in turn display red colored marks on the page.Then usually save button is also becoming enabled.
But, I want to change this behavior.When some error mark appears on the page, I don't want to get the save button enabled,.It shouldn't allow the user to save the model in the error stage.
The save button should be disabled, How can I achieve this.
Kindly clear my doubt.

The editor generated by EMF uses a commandstacklistener to fire a PROP_DIRTY to the editor. If this property is fired, the underlying framework will ask the editors #isDirty Method for the dirty state. This is the place where you can implement your logic.
#Override
public boolean isDirty() {
Diagnostic diagnostic = validateMyModel();
return ((BasicCommandStack)editingDomain.getCommandStack()).isSaveNeeded() && diagnostic.getSeverity() == Diagnostic.OK;
}
This case doesn't cover the usecase, that the editor could have been already dirty when the user makes a not-valid edit on the model.
But that is not the best way IMHO. Because if the user closes the editor all changes of the model are lost, without any notification (because of the missing dirty-flag). So he probably did 100 valid modifications, 1 invalid and loses his changed model.
A better way is to show a warning-message if the user wants to save the dialog. If there are errors in the dialog the editor cannot change its state from dirty to not-dirty and the user has to
correct all erros or
close the editor and looses all his changens
To achieve that you have to implement in your doSave(IProgressMonitor progressMonitor) method a dialog to show the errors. The more tricky part is to override the default-behavior of closing a dirty editor. The workbench will show a dialog with, Yes, No and Cancel
To override this behavior you have to implement the interface org.eclipse.ui.ISaveablePart2 in your editor to override the promptToSaveOnClose() method. In this method there must be again your logic that checks for errors in the model. If there are errors, this method has to return ISaveablePart2.CANCEL so that editor is not closable as long as there are errors in the dirty model.
HTH Tom

Related

Can I dynamically change the label of a Siebel button?

In our Siebel 7.8 (high interactivity) application, we have a form applet with a Pause / Resume custom button which does the following, depending on the current record's status:
If the status is "queued" or "active", it switches it to "paused".
If the status is "paused", it switches it back to whatever it was before.
If the status is another one ("completed", "error", etc), the button is disabled.
Is it possible to change the label dynamically? So that it would read Pause in the first case, and Resume in the second.
Off the top of my head the only way I can think of doing this would be with a browser script placed both in the Applet_Load and Applet_ChangeRecord events, something like:
var button = this.FindActiveXControl("Name Of My Button Control");
var status = this.BusComp().GetFieldValue("Status");
if (status == "paused") {
button.innerHTML = "Resume";
} else if ((status == "queued") || (status == "active")) {
button.innerHTML = "Pause";
} else {
// the button will be disabled via PreCanInvokeMethod, but we hide it too
button.style.visibility = "hidden";
}
Even if that worked (it should, but I haven't tried it)... I really hate browser scripts in Siebel, they always bring more trouble than solutions. Besides, I still would have to deal with changing the label when the button is clicked too... maybe checking the Applet_InvokeMethod browser event as well.
Is there any way of changing a button's label, based on the current record data, without coding1? All I have found searching online is this trick to change the applet label based on a calculated field, but nothing for buttons.
1: By without coding, I mean not coding the label change myself. It would be perfectly fine if I have to write a business service method to be invoked by Siebel somehow.
There are a few options potentially available:
We did something similar, but we are in a later Siebel version with Open UI. So instead of Browser Script we added code to custom Presentation Model and Physical Renderer JavaScript files. Even though you don't wish to, if you had to resort to something similar using Browser Scripts, you might prefer this over manipulating the text of one button.
I created two button controls: One that displayed Tag and the other Untag. They both call the same method. I added a flag field to the BC. (You might could do the same with a calculated field that is based on certain [Status] values.) In the JS files I put code to check that flag field and then, based on the flag field value, display one button and hide the other.
I did not start with Siebel until 8.1, so I cannot recall if this would be available in 7.8. And this only works on Order Management Applets with a class of CSSSWEFrameListHC (which is why I said "potentially available" options):
There exists an Applet User Property called Hide Control n [See Siebel Developer's Reference v7.8 -> Ch 4: User Properties -> Setting Numbered Instances of a User Property for the use of n in User Properties.]
First, create two separate controls - one that displays Pause and the other Resume. The User Property could be used something like this:
Applet User Properties
Name Value
Hide Control 'Name Of My Pause Button Control', '[Status] = "paused"'
Hide Control 1 'Name Of My Resume Button Control', '[Status] = "queued" OR [Status] = "active"'
You could possibly OR all the other [Status] values into these if you wanted to hide it and not just disable it.
Use Toggle Applets. [See Configuring Siebel eBusiness Applications v7.7 -> Ch 13: Configuring Screens and Views -> Example of Configuring Applet Toggles.]
Copy your existing Applet that has Resume, and modify that button Control in the copy to display Pause. Name the new Applet something like My Form Applet - Pause Button.
Then in Tools drill into your existing Applet, click the Applet Toggle child object, add a New Record, and make it something like this:
If you want this to toggle immediately when the [Status] changes, you'll need to set Immediate Post Changes to TRUE on the [Status] field on the BC. (This could cause performance issues, so be mindful.) Otherwise the Applet won't toggle until the record is saved.
Or you could possibly create a calculated flag field on the BC based on [Status] values, set it's Immediate Post Changes to TRUE, and base the Applet Toggle on that field.
DISCLAIMER: Other than our version of #1, I have not attempted any of these.

Prompt user to save changes when closing MFC view

I have an MFC MDI application, in which it is possible for documents to have multiple views, and for users to customise and then save layout data for the views. This data is associated with the views, not the documents.
I would like to prompt the users to save if they choose to close a view with unsaved layout changes, and am running into problems, as it seems MFC is only geared towards changes in the document. Here are some approaches I've tried:
Override CDocument::SaveModified function, which gets called by the framework when a document is closed. In this function, I send a message to all the document's views, which can then check for unsaved changes and prompt the user.
Perform the check inside the View's destructor.
Perform the check inside the View's OnClose handler
Each of these approaches has problems. (1) is the best, but it fails to deal with cases where there are several views onto one document, and the user closes one of the views. As the document is still open, SaveModified is not called.
The problem with (2) is that on application shutdown, the application has already disappeard by the time any CView destrutors are called. This can leave an orphan dialog box open on the desktop. This is also the case if I try performing the check inside OnDestroy.
I can't get (3) to work - I can't get my views to respond to WM_CLOSE.
Currently, my best solution is to do both (1) and (2), but this requires some smelly logic to prevent the app from prompting the user to save view changes twice on app shutdown.
Anyone know of a better way of doing this? Where is the correct place to hook in?
I'm not sure if it is your solution, but I have several views that can not close on condition and I handle them in DestroyWindow( ). And a message box there does come up over the app before it closes down. So try using DestroyWindow( ) rather than the destructor.
Concur.
ON_WM_DESTROY()
afx_msg void OnDestroy();
does the trick. It will not prevent the window from closing, but the question didn't request it.

Disabling action but keep menu enabled

Here is how I create menu on Action item.
QAction * menuHolder = new QAction("Holder");
menuHolder->setMenu(new QMenu());
menuHolder->menu()->addAction(new QAction("Menu item"));
My problem is how to disable menuHolder but keep menu associated to the action enabled(arrow near menuHolder should still be enabled).
I've tried something like this, but this doesn't work:
menuHolder->setEnabled(false);
menuHolder->menu()->setEnabled(true); ?
Edited after comments:
It seems you're looking for a solution for a problem you don't have. You could prefectly handle that scenario as many many others applications do:
If the user click to save and don't have permissions just notify about that, and if you want, you could explain that he/she needs to save the file with another name.
In most of applications the user will look for File -> Save as for doing that.
So, separate the actions, the way you are trying to do alse can confuse the user and never find the action Save as, sice is under a disabled icon.

MFC SDI Text Editor

I am creating an MFC SDI explorer style application (it has a splitter bar and the right-hand pane is the text-edit area, left-hand pane is the tree-view)
My right-hand pane is a CRichEditView.
I want to be able to detect when a user has edited the text so that a flag is set to show that a change has been made but has not been saved. I have tried several ways of doing this e.g. catching WM_KEYDOWN in PreTranslateMessage, but this catches everything and prevents the keypresses from editing the view. I have also tried adding ON_WM_KEYDOWN() to the message map in the MyView.cpp. Again, this seems to prevent the keystrokes from having any affect on the text in the view. I want to allow the user to edit the text in the view, but the application to know that this has been done.
Please help - I have looked for hours for ways to do this.
Many thanks
Adding ON_WM_KEYDOWN() to the message map is probably the correct approach. You must make sure that your implementation of the OnKeyDown() method calls the base class method so that the message gets passed on as appropriate.

how to put a derived control ("MyCEdit") onto a dialog or property page?

This should be obvious, but I can't find anywhere that spells it out.
I want to derive a MyCEdit from CEdit so I can override the OnChar handler and do useful things with keyboard input to an edit box. Each edit box I have fills the client area on a MyCPropertyPage (derived from CPropertyPage), and several such pages make up a tab control used to display diagnostics. I leave the edit boxes enabled and not read only (for aesthetics, not function).
In the resource editor (or elsewhere) how to I tell Visual Studio that I want a certain edit box to be a MyCEdit rather than a CEdit? Can I hope to just override the OnChar in MyCEdit to intercept characters... or do I have to override OnKeyDown as well - I have read a suggestion to this effect, but found no MS source article spelling out why.
So far, the only thing I can easily override is MCPropertyPage::OnChar... but that seems to get bypassed, and characters just go straight to the edit box child.
HI if i understand you need you can add simple edit to your page, then add control variable and write MyCEdit in class name field. And dont forget to set parent notify option in resource editor on your MCPropertyPage.