Is there any way to change dialog cancel button in x++? - dialog

I am using Dialog class to make my dialog. I added there custom lookup and field, but it looks like cancel button doesnt work as it supposed to work. I dont know a lot about Dialog class and how it works... Is there any suggestions how to change Cancel button to its normal function - cancel the dialog. Right now it throws info that is supposed to throw out on Process when u press Ok on Dialog.
My current code:
class copyline
{
public void clicked()
{
Counter createdRecordCnt;
Trans trans;
Table table;
MultiSelectionHelper helper = MultiSelectionHelper::construct();
JournalId journalId;
helper.parmDatasource(Trans_DS);
MyClass MyClass= new MyClass();
MyClass.dialog();
trans = helper.getFirst();
while(trans.RecId != 0)
{
MyClass.parmJournalTrans(trans);
MyClass.parmJournalId(JournalId);
if (journalId)
{
MyClass.parmJournalTrans(trans);
MyClass.parmJournalId(JournalId);
MyClass.run();
}
else
{
if (MyClass.prompt())
{
MyClass.run();
journalId = MyClass.parmJournalId();
}
}
createdRecordCnt++;
trans = helper.getNext();
}
Info(strFmt("#LabelFile:Label", createdRecordCnt, MyClass.parmJournalId()));
}
}
I have class with Dialog object, validations, lookup etc.
Dialog on class:
public Object dialog()
{
Dialog dialog = super();
FormBuildStringControl control;
dialog.caption("#LabelFile:Label");
Journal = dialog.addField(extendedTypeStr(MyEDT));
control = Journal.control();
control.registerOverrideMethod(methodstr(FormStringControl, lookUp), methodStr(MyClass, journalTypeLookup), this);
return dialog;
}

Related

Is there a way to make custom lookup on dialog field on Microsoft Dynamics 365?

I have problems with my dialog field. I have button that opens dialog tab with field. It was supposed to show on that field lookup exact records(i guess i need select there by one field value). Right now i have this code:
DialogField Journal = dialog.addField(extendedTypeStr(JournalId));
This dialog line adds a field with all values on that EDT. I have 3 journal types - NEW, UPDATE, DELETE. Right now on that field lookup it shows me all 3 journal types. I want to make custom lookup that shows exact type , example - if i click that button on journal that has type "NEW", then it should show only "NEW" type of journal types on lookup. I heard there is something like dialog.addLookup or something. Can someone help me?
You already added your dialog field (in the dialog() method). Now add the dialogRunPost() method that is executed after the form GUI is initialized. At that point you can fetch the underlying FormStringControl behind the dialog field. Subscribing to the FormStringControl.OnLookup event allows you to override the lookup.
I did not have some journal data available, so I created a similar example with customers. My example dialog (MyDialog) takes a source customer (customerCaller) and shows a dialog with a custom lookup that only shows customers with the same customer group.
My example is also a standalone, runnable class and is not called from a form. Comments have been added to indicate where this affects the code.
Full example
public class MyDialog extends Runbase
{
// fields
protected Args args;
protected CustTable customerCaller;
protected DialogField dfCustomerId;
// construct
public static MyDialog newArgs(Args _args)
{
MyDialog ret = new MyDialog();
ret.args = _args;
return ret;
}
// initialize
public boolean init()
{
boolean ret = super();
// validate and fetch caller
if (args.record() && args.record().TableId == tableNum(CustTable))
//if (args.caller() && args.caller().dataset() == tableNum(CustTable)) --> when called from form
{
customerCaller = args.record();
//customerCaller = args.caller().record();
}
else
{
throw error(Error::missingRecord('My Dialog'));
}
return ret;
}
// build dialog
public Object dialog()
{
Dialog ret = super();
// optional reference to visualize the input
ret.addText('Caller customer group = ' + customerCaller.CustGroup);
// add field
dfCustomerId = ret.addField(extendedTypeStr(CustAccount)); // default lookup = all CustTable.AccountNum values
return ret;
}
public void dialogPostRun(DialogRunbase dialog)
{
super(dialog);
// subscribe to lookup event
FormStringControl fscCustomerId = dfCustomerId.control();
fscCustomerId .OnLookup += eventhandler(this.customerId_OnLookup);
}
// custom lookup for customer id
protected void customerId_OnLookup(FormControl _sender, FormControlEventArgs _e)
{
// cancel default
FormControlCancelableSuperEventArgs eventArgs = _e;
eventArgs.CancelSuperCall();
// define lookup query (list all customers with same customer group as input customer)
Query query = new Query();
QueryBuildDataSource qbds = SysQuery::findOrCreateDataSource(query, tableNum(CustTable));
SysQuery::findOrCreateRange(qbds, fieldNum(CustTable, CustGroup)).value(SysQuery::value(customerCaller.CustGroup));
// do lookup
SysTableLookup lookup = SysTableLookup::newParameters(tableNum(CustTable), _sender);
lookup.parmQuery(query);
lookup.addLookupfield(fieldNum(CustTable, AccountNum), true);
lookup.addLookupfield(fieldNum(CustTable, CustGroup));
lookup.performFormLookup();
}
// run dialog
public static void main(Args _args)
{
// I am running this dialog directly (not from a form), generating some random input
CustTable customer;
select firstonly customer where customer.CustGroup != '';
_args.record(customer);
// end of random input
MyDialog md = MyDialog::newArgs(_args);
md.init();
if (md.prompt())
{
md.run();
}
}
}
Result

How to send back to custom class which object of that class was clicked

I am stack at this problem can't figure out how to do it properly. [Haxe/OpenFL]
I want to make following menu. On screen for player display three images/buttons. When player clicks on one of the images/buttons a text with description appears under that button.
My is, i dont know how to send from Main (where i create this buttons and using them), send info to custom class of this images/buttons, what specific button/image was pressed.
Here is example code, first from custom class of the images/buttons:
class CusstomButtons extends Sprite {
var buttonImagePath:String;
var _buttonImagePath:String;
var buttonName:String;
var _buttonName:String;
var button1Btmp:Bitmap = new Bitmap ();
var button1Sprt:Sprite = new Sprite();
var button2Btmp:Bitmap = new Bitmap ();
var button2Sprt:Sprite = new Sprite();
var buttonText1:TextField = new TextField ();
var buttonText2:TextField = new TextField ();
public function new(buttonImagePath, buttonName) {
super();
_buttonImagePath = buttonImagePath;
_buttonName = buttonName;
createButton ();
}
public function createButton () :Void {
if (_buttonName == Button1){
button1Btmp = new Bitmap (Assets.getBitmapData (_buttonImagePath));
button1Sprt.addChild(button1Btmp);
addChild(button1Sprt);
//Here goes the code for button position and tweening
}
if (_buttonName == Button2){
button2Btmp = new Bitmap (Assets.getBitmapData (_buttonImagePath));
button2Sprt.addChild(button2Btmp);
addChild(button2Sprt);
//Here goes the code for button position and tweening
}
}
public function displayButtonDescrition () :Void {
if (button1) {
buttonText1.text = "Some text for Button 1"
addChild(buttonText1);
//Here goes code for button position and etc
}
if (button2) {
buttonText2.text = "Some text for Button 2"
addChild(buttonText2);
//Here goes code for button position and etc
}
}
}
And here is code from main:
class Main extends Sprite {
public var button1Menu:CusstomButtons;
public var button2Menu:CusstomButtons;
public function new () {
super ();
button1Menu = new CusstomButtons ("path/button1", "button1");
button1Menu = new CusstomButtons ("path/button1", "button2");
}
public function createButtonMenu ():Void {
button1Menu.createButton();
addChild(button1Menu);
button2Menu.createButton();
addChild(button2Menu);
button1Menu.addEventListener(MouseEvent.CLICK, onClick);
button2Menu.addEventListener(MouseEvent.CLICK, onClick);
}
public function onClick (event:MouseEvent):Void {
if (event.currentTarget == button1Menu) {
button1Menu.displayButtonDescrition();
}
if (event.currentTarget == button2Menu) {
button2Menu.displayButtonDescrition();
}
}
}
The main question is how to use one function to display different description texts.
You could make a static field in the Button class to hold all created instances of it.
static var instances = new Array();
Then in the Button constructor store the instance that is currently being created
instances.push(this);
Finally, from the main class call a static method in the button class, passing the clicked instance:
public static function setClickedInstance(instance:Button):Void{
//manipulation code goes here
}
And in the main class call the method when necessary:
Button.setClickedInstance();
Sorry if above doesn't compile as I couldn't test it right now. If not, it probably just needs a bit of tweaking.
An alternative would be to add a mouse listener in the Button class itself, but then you wouldn't have control in the main class when to "react" on clicks and when not.

LWUIT 1.4 : Why is there sometimes duplicates in this TextArea?

I created a class from Dialog which contains a TextArea :
public class Alert extends Dialog {
private Container c = new Container(new BorderLayout());
private Label titre = new Label("Mobile Banking");
private TextArea chp;
private Command[] comms;
public Alert(String text, Command[] comms)
{
super();
titre.setUIID("titre_alert");
titre.setAlignment(Label.CENTER);
this.comms = comms;
setAutoDispose(true);
for (int cmd=0; cmd<comms.length; cmd++)
addCommand(comms[cmd]);
chp = new TextArea();
chp.setEditable(false);
chp.setAlignment(Label.CENTER);
chp.getSelectedStyle().setBorder(null);
chp.getUnselectedStyle().setBorder(null);
chp.getSelectedStyle().setBgColor(this.getStyle().getBgColor());
chp.getUnselectedStyle().setBgColor(this.getStyle().getBgColor());
if (text.length() % 2 != 0)
text = " ".concat(text);
while (text.substring(0, (text.length()/2)+1).length() < chp.getMaxSize()/2)
{
text = " ".concat(text);
}
chp.setText(text);
c.addComponent(BorderLayout.NORTH, titre);
c.addComponent(BorderLayout.CENTER, chp);
}
public Command affiche()
{
return show(null, c, comms);
}
}
Inside a Form I start a thread which makes a HttpConnection call and other tasks. If the tasks end successfully then I call the affiche() method of the above class Alert :
alert = new Alert("Chargement effectué avec succès !", new Command[]{ok});
cntnr.removeComponent(cPatienter); // container displaying the "please wait..."
repaint(); // repainting the Form
if (alert.affiche() == ok) // showing the confirmation of successfullness of the task
{
alert.dispose();
controller.displayScreen("Menuprincipale");
}
The problem is that , sometimes , the text shown when calling the affiche() method is duplicated : it should show only the text Chargement effectué avec succès ! but sometimes it shows the text and also Chargement effectué.
So how to make it that only the text parameter is only shown but not duplicated ?
You are invoking LWUIT on a separate thread which is illegal. You need to use Display.callSerially to avoid a race condition in the text layout code. Something like this:
Display.getInstance().callSerially(new Runnable() {
public void run() {
// your LWUIT code here, no need for repaints
}
});
A better approach is to use LWUIT4IO for your networking since it does this seamlessly for you.

Preventing TabControl selection in Silverlight

Is there any way to prevent the change of a tab in TabControl in Silverlight 4?
A simple case is when I've got a form with some data, and I want to ask the user if he/she wants to save this data before actually changing the tab.
I've seen code examples on how to do this in WPF, but not in Silverlight.
What can I do to stop the tab from changing?
Bind SelectedIndex to a property on your data context.
<sdk:TabControl SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">
<sdk:TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</sdk:TabItem>
<sdk:TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</sdk:TabItem>
</sdk:TabControl>
In the SET accessor, write your code to check whether the user really wants to do what they're trying to do.
public class Context : INotifyPropertyChanged
{
int _SelectedIndex = 0;
public int SelectedIndex
{
get
{
return _SelectedIndex;
}
set
{
MessageBoxResult result = MessageBox.Show("Do you want to save?", "Really?", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
_SelectedIndex = value;
}
RaisePropertyChanged("SelectedIndex");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
Net effect is, if the user chooses 'cancel' on the dialogue the private variable is never changed - the PropertyChanged event fires, rebinding the selected index to the existing value.
Hope this is what you were trying to accomplish.
UPDATE (11/10/2012) - Alternate method (possibly for SL5?). Write code behind to tie into SelectionChanged event of your TabControl, reset the tab control's selected item property based on your test.
private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count > 0)
{
MessageBoxResult result = MessageBox.Show("Do you want to save?", "Really?", MessageBoxButton.OKCancel);
if (result != MessageBoxResult.OK)
{
((TabControl)sender).SelectionChanged -= new SelectionChangedEventHandler(TabControl_SelectionChanged);
((TabControl)sender).SelectedItem = e.RemovedItems[0];
((TabControl)sender).SelectionChanged += new SelectionChangedEventHandler(TabControl_SelectionChanged);
}
}
}

How to ticker List elements when they are Commands?

If I create a List based on an array of Commands, and the text of some Commands are not entirely shown in the List, although the List preferredWidth is set to the Form preferredWidth, how to ticker them ?
Thank you very much
Add the below class in your midlet class or create a new class file for that:
class TickerRenderer extends DefaultListCellRenderer {
private DefaultListCellRenderer selectedRenderer = new DefaultListCellRenderer(false);
private List parentList;
public TickerRenderer() {
super(false);
}
public boolean animate() {
if (parentList != null && parentList.getComponentForm() != null) {
if (selectedRenderer.isTickerRunning()) {
if (selectedRenderer.animate()) {
parentList.repaint();
}
}
}
return super.animate();
}
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
if (isSelected) {
selectedRenderer.getListCellRendererComponent(list, value, index, isSelected);
// sometimes the list asks for a dummy selected value for size calculations and this might
// break the tickering state
if (index == list.getSelectedIndex()) {
if (selectedRenderer.shouldTickerStart()) {
if (!selectedRenderer.isTickerRunning()) {
parentList = list;
list.getComponentForm().registerAnimated(this);
selectedRenderer.startTicker(UIManager.getInstance().getLookAndFeel().getTickerSpeed(), true);
}
} else {
if (selectedRenderer.isTickerRunning()) {
selectedRenderer.stopTicker();
}
}
}
return selectedRenderer;
} else {
return super.getListCellRendererComponent(list, value, index, isSelected);
}
}
}
Use it like this:
List cmdList = new List(cmds);
cmdList.setListCellRenderer(new TickerRenderer());
Try this code, it will show list in dialog box on clicking "Show list" command and will also enable ticker initially. Below is the code which shows how to use the above mentioned class to see ticker in list when list is contained in dialog.
Don't forget to make your list final so that it can be used in inner classes.
form.addCommand(new Command("Show list") { // add command in form and override its actionPerformed method
public void actionPerformed(ActionEvent evt) {
Dialog d = new Dialog() { // create an instance of dialog and make it an inner class so that you can override onShow() method and set focus on list when dialog gets initialized and also can set its index to ur preferred one (here it's 0)
protected void onShow() { // overriding of onShow() method
list.requestFocus(); // set focus on list
list.setSelectedIndex(0); // set selected index to 0
}
};
d.addComponent(list); // add list in dialog
d.show(); // show dialog
}
});
This code shows my list in dialog and starts ticker initially. If it doesn't help, post your code, i will try to see it.

Resources