Call Pop-Up for WebDynpro from a Business AddIn? - abap

We got a Web Dynpro Application which was created with the Floorplan Manager.
By clicking a specific button I start a Business AddIn which check some conditions and then it should show a popup on the screen with a message for the user.
Is there a way I can accomplish that?

One way to get a PopUp (eg confirmation) window in Floorplan applications is to overwrite the NEEDS_CONFIRMATION method of the Interface IF_FPM_GUIBB_*_EXT inside your feeder-class.
Create a reference to cl_fpm_confirmation_request and put this one in the export-parameter EO_CONFIRMATION_REQUEST of the Method.
By Example:
METHOD if_fpm_guibb_list_ext~needs_confirmation.
DATA li_req TYPE REF TO cl_fpm_confirmation_request.
CASE io_event->mv_event_id.
WHEN 'YOUR_EVENT_ID'.
CREATE OBJECT li_req
EXPORTING
it_confirmation_text = 'Plaintext in Content of Popup'
iv_window_title = 'Title of the Popup'
iv_button_text_approve = 'Text Approve-Button'
iv_button_text_reject = 'Text Reject-Button'
.
eo_confirmation_request = li_confrequ.
ENDCASE.
ENDMETHOD.
The method will be called before the PROCESS_EVENT-Method an will override it when you cancel the popup.
Please be aware that every GUIBB-Implementation has it´s own extension interface, e.g. List, Tree, ...
For a deeper look inside popups in FPM or custom-popups have a look into https://blogs.sap.com/2013/11/26/popups-in-floorplan-manager/

Related

Display call transaction screen in a Splitter-container

I have a program which displays a splitter-container with two columns:
Left side displays a control tree (this is OK)
Right side should displays a custom TCode (not sure how to do this bit)
On double-click of a tree node, it calls a transaction which opens a screen, but it opens in a new window.
How to open the screen in the right-side window?
Minimal reproducible example:
Create the transaction code ZCALL_ZPRG1 via SE93, so that it calls the program ZPRG1
Create the program ZPRG1 (minimalist screen):
REPORT zprg1.
PARAMETERS test AS CHECKBOX.
Create the program ZPRG2 (splitter and tree):
REPORT zprg2.
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
METHODS:
pbo,
on_node_double_click FOR EVENT node_double_click OF cl_gui_simple_tree.
DATA:
tree TYPE REF TO cl_gui_simple_tree,
itab TYPE TABLE OF mtreesnode,
splitter TYPE REF TO cl_gui_splitter_container.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD pbo.
CHECK tree IS NOT BOUND.
CREATE OBJECT splitter
EXPORTING
parent = cl_gui_container=>screen0
rows = 1
columns = 2.
itab = VALUE #(
( node_key = '1'
text = 'Double-click me' ) ).
CREATE OBJECT tree
EXPORTING
parent = splitter->get_container( row = 1 column = 1 )
node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single.
tree->add_nodes(
table_structure_name = 'MTREESNODE'
node_table = itab ).
SET HANDLER on_node_double_click FOR tree.
DATA events TYPE cntl_simple_events.
CALL METHOD tree->set_registered_events
EXPORTING
events = VALUE #( ( eventid = tree->eventid_node_double_click ) )
EXCEPTIONS
OTHERS = 4.
ENDMETHOD.
METHOD on_node_double_click.
CALL TRANSACTION 'ZCALL_ZPRG1'.
ENDMETHOD.
ENDCLASS.
DATA: app TYPE REF TO lcl_app.
PARAMETERS dummy.
INITIALIZATION.
CREATE OBJECT app.
AT SELECTION-SCREEN OUTPUT.
app->pbo( ).
AT SELECTION-SCREEN ON EXIT-COMMAND.
app->splitter->free( ).
Run ZPRG2
Double-click the tree node
In the SAP GUI, it is possible to mix screens of dynpro technology and GUI controls of the SAP Control Framework in these ways:
Screen and Docking Containers ; these containers may be displayed at any of the 4 sides of the screen
In these containers can be placed GUI controls (including splitter containers)
Screen containing a so-called Custom Container area in which can be placed GUI controls (including splitter containers)
Popups can be displayed over any dynpro screen or GUI control; those popups may also contain any (other) dynpro screen or GUI control; they are completely independent from the screen below. Popups may also be displayed over popups.
It is not possible to embed a dynpro screen inside a GUI control (including containers) in any manner.
So, in your case, the only solution is to use a docking container on the left of your dynpro screen. But only the program which displays the dynpro screen is allowed to "add" the docking container (i.e. CALL TRANSACTION or SUBMIT cannot be used).
Consequently, ZPRG2 must handle both your GUI control and a dynpro screen. You have two options to handle the dynpro screen:
Either ZPRG2 handles it (everything is done by ZPRG2, you don't need ZPRG1)
Or you only define a subscreen area inside the dynpro screen of ZPRG2, and you include a subscreen from ZPRG1 which handles all the initializations and interactions of the subscreen.
The second solution is recommended because it permits the Separation Of Concerns".
The code below is a minimal example to demonstrate how it could work, that will allow you to debug and understand better; there are so many things to explain that I prefer to let you ask questions in the comments (or new questions); be aware that many of the algorithm, statements and tricks below are not advised, I use them just because they are much shorter. You will end up with a much more complex program than this one.
Program ZPRG1 (right side, show/hide UI elements to react to double click at left side):
REPORT zprg1.
DATA display TYPE abap_bool VALUE abap_false.
SELECTION-SCREEN BEGIN OF SCREEN 0100 AS SUBSCREEN.
PARAMETERS test AS CHECKBOX.
SELECTION-SCREEN END OF SCREEN 0100.
AT SELECTION-SCREEN OUTPUT.
IF display = abap_false.
LOOP AT SCREEN.
screen-active = '0'.
MODIFY SCREEN.
ENDLOOP.
ENDIF.
FORM toggle_display.
IF display = abap_false.
display = abap_true.
ELSE.
display = abap_false.
ENDIF.
ENDFORM.
Program ZPRG2 (left side tree + handling of subscreen area at the right to include ZPRG1 screen):
REPORT zprg2.
DATA okcode TYPE syucomm. " global variable for dynpro 0200 "OKCODE" element
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
METHODS:
pbo,
pai,
on_node_double_click FOR EVENT node_double_click OF cl_gui_simple_tree.
DATA:
tree TYPE REF TO cl_gui_simple_tree,
itab TYPE TABLE OF mtreesnode,
docking TYPE REF TO cl_gui_docking_container.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD pbo.
SET PF-STATUS space. " <=== trick to activate buttons in the system toolbar
CHECK tree IS NOT BOUND.
CREATE OBJECT docking
EXPORTING
repid = sy-repid
dynnr = sy-dynnr
side = docking->dock_at_left
extension = 400 " pixels
EXCEPTIONS
OTHERS = 6.
itab = VALUE #(
( node_key = '1'
text = 'Double-click me' ) ).
CREATE OBJECT tree
EXPORTING
parent = docking
node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single.
tree->add_nodes(
table_structure_name = 'MTREESNODE'
node_table = itab ).
SET HANDLER on_node_double_click FOR tree.
DATA events TYPE cntl_simple_events.
CALL METHOD tree->set_registered_events
EXPORTING
events = VALUE #( ( eventid = tree->eventid_node_double_click
appl_event = 'X' ) ) " <=== to trigger the PAI
EXCEPTIONS
OTHERS = 4.
ENDMETHOD.
METHOD on_node_double_click.
PERFORM toggle_display IN PROGRAM zprg1.
ENDMETHOD.
METHOD pai.
CASE okcode.
WHEN 'BACK' OR 'RW' OR '%EX'. " one of the exit buttons in system toolbar
docking->free( ). " free container and inner controls
SET SCREEN 0. " to return after the current CALL SCREEN
ENDCASE.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA: app TYPE REF TO lcl_app.
CREATE OBJECT app.
CALL SCREEN 200.
MODULE status_0200 OUTPUT.
app->pbo( ).
ENDMODULE.
MODULE user_command_0200 INPUT.
app->pai( ).
ENDMODULE.
Dynpro 0200 of program ZPRG2:
The layout contains a huge subscreen area named SUBAREA, and the OKCODE element is to be assigned the name OKCODE (which is mapped to the global variable of ZPRG2 having the same name)
The flow logic contains this code:
PROCESS BEFORE OUTPUT.
MODULE status_0200.
CALL SUBSCREEN subarea INCLUDING 'ZPRG1' '0100'.
PROCESS AFTER INPUT.
CALL SUBSCREEN subarea.
MODULE user_command_0200.

Can we set the element ID for component created in the code like the ID in application model (e4xmi)?

I created a RCP app with a part. In the part, I created a TreeViewer. Can I set an ID for this viewer so that others plugins can find this viewer by ID? How can we acquire this?
No, you can't do this.
The contents of a part are not in the application model and can't have model ids.
You have to use the findPart method of EPartService to find the part and then call some method that you write in the part object to get the viewer.
MPart part = partService.findPart("part id");
MyPartClass myclass = (MyPartClass)part.getObject();
TreeViewer viewer = myclass.getViewer();

How can I change the program header in sap abap?

I want to change the header name of the ABAP program. What can I do or where can I find the option to edit the header?
Two ways for this:
Set it in program options. Select the program and check menu Goto / Attributes.
Or you can create a GUI title and set it via ABAP. This overwrites attributes' setting.
More about how to achieve: here.
To change the program header is more easier than it seems.
Just open you program via SE38 -> Goto -> Properties -> Check the title field and change -> Save
And you are done. :)
I have this.
Usually is changing the name in atributes with transaction se38, but sometimes this don't work, you need in the transaction se80, create a title GUI, if yuou don't have a title created, righ clic in the program name, create -> GUI title.
And put your name and code.
and in your program (se38) in PBO, you have to call the title with
SET TITLEBAR '100' (Put your title code)
(100 is the title code), but this instruction have to need inside of a moodle, if is outside don't will work.
I use the first moodle that i have in my PBO (i don't know if is the best decition or the right form, but is a way and works).
finally the title change
The path is SE38 -> (Put Program Name) -> Now open the program in edit mode -> Select the option GOTO -> select Properties Change the program title.

How to automate a splitButton using Rautomation ( adapter msuia)

I am trying to automate IE11 notification bar ( while downloading file) using Rautomation. Using MSUIA adapter I am able to catch the the save button. But I want to use Save As to supply the file location and name. But I cannot do that.
When seeing with UIspy I see that there is a splitbutton with name "Save". This splitbutton has another child splitbutton with name "" ( which is basically the down arrow) - I am not able to get to this control.
iemainwindow_local = RAutomation::Window.new(:class=>"IEFrame" , :adapter => :ms_uia )
ienotificationbar_frame = iemainwindow_local.child(:class=>"Frame Notification Bar")
ienotificationbar = ienotificationbar_frame.child(:class=>"DirectUIHWND")
if ienotificationbar.exists?
ienotificationbar.activate
sleep 1
mycontrol = ienotificationbar.control(:value =>"Save")
mycontrol2= mycontrol.control(:children_only => true)
mycontrol2.exist?
mycontrol.click
end
Getting error at this line mycontrol2= mycontrol.control(:children_only => true)
undefined method `control' for #<RAutomation::Adapter::MsUia::Control:0x4108e60>
Any idea how to get over this block?
I understand that there should be a menu and menuitems associated with the splitButton and when I click on down arrow besides Save, at UISpy I see that menu/ menu item is getting created directly under Desktop window ( though the processID is same ) - how to catch the menuitem Save as?
The Problem
Unfortunately, the :ms_uia adapter for RAutomation is not able to do this in its current form. I know this because I have written a lot of the UIA adapter for it :) The problem is that the current API doesn't allow you to really walk the tree like that (as you found out) because the Control class doesn't have a #control method. If the "Save" button had a native window handle, you'd be able to do this:
ieframe = RAutomation::Window.new(class: 'IEFrame')
save = RAutomation::Window.new(hwnd: ieframe.control(value: 'Save').hwnd)
save.control(index: 0)
Since it does not, unfortunately there isn't a reliable way to get down to it that I am aware of since it doesn't have any identifying properties about it (other than being a child of the "Save" button).
Alternative
I've written another gem called uia, which acts as a low-level wrapper around UI Automation and allows you to work more closely with UI Automation and interact with it how you see it within tools like UI Spy. Eventually, I will use this gem in RAutomation but have not had the time yet. To get down to the "Save As..." split button control in your circumstance, you can do this:
ieframe = UIA.find_element(title: /Thanks for downloading/)
save_as = ieframe.find(name: 'Save').find(control_type: :split_button)
save_as.as(:invoke).invoke
The save_as.as(:invoke) will treat the found "Save As" Element as something that implements the Invoke pattern, and then you can call the #invoke method to get the menu to pop.
Hope this helps!

NSTokenField click completion list item

I have an NSTokenField in my application and I implemented the tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: method in which I specify the receiver’s tokenizing character set with the setTokenizingCharacterSet: method:
def tokenField(tokenField, completionsForSubstring:substring, indexOfToken:tokenIndex, indexOfSelectedItem:selectedIndex)
tokenField.setTokenizingCharacterSet(NSCharacterSet.whitespaceAndNewlineCharacterSet)
end
It works as expected when I click on the space bar or the enter button. I would also like to have the same behavior when I click on one of the item of the completion list with my mouse.
How is that possible?
Thanks for your help.
I don't know if it's possible to have this behaviour with a NSTokenField.
But you should take a look at MTTokenField which do what you want out of the box.
To do so, you will have to:
1.Create an Xcode Project as a Static Library(Do not enable ARC).
2.Save your project to vendor/MTTokenField
3.Drag and drop all the files of MTTokenField located in the subdirectory 'MTTokenField' to your new XCode project. Choose to copy the files.
4.Add this to your rakefile in order to compile and link the library with your Rubymotion project.
app.vendor_project("vendor/MTTokenField/", :xcode, :xcodeproj => "MTTokenField.xcodeproj", :target => "MTTokenField", :products => ["libMTTokenField.a"], :headers_dir => "MTTokenField")
5.In Interface Builder change the class of your NSTokenField to NSTextField and then set its custom class to MTTokenField, and also change the custom class of the cell: MTTokenFieldCell instead of NSTextFieldCell.
6.Then you have to set the delegate of your MTTokenField to a class which has to respond to :
def tokenField(tokenField, completionsForSubstring: substring )
# your have to return an array containing your results matching substring.
end
And that's it. It should work.
Hope it helps !
I found another solution using NSTokenField instead of MTTokenField.
In the delegate of my NSTokenField, I used the controlTextDidChange method of NSControl which is called anytime I write a character in my token field. In this method I check if there is a NSLeftMouseUp event which is triggered, and if it's the case, I simulate a click on Return. And that's it.
def controlTextDidChange(aNotification)
application = NSApplication.sharedApplication
event = application.currentEvent
if event.type == NSLeftMouseUp
e1 = CGEventCreateKeyboardEvent(nil, 0x24, true)
CGEventPost(KCGSessionEventTap, e1)
end
end
There is one more thing to do to make it properly work: the issue here is that if I have a completion list with 3 items for instance, one of them will be selected by default, let's say the first one. In this case, the solution will work as expected if I click the second or the third item but I will have to double click the first item to make it work.
To fix this, turn off the autocompletion and only display the suggestion box, i.e add this line to the tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: method:
selectedIndex[0] = -1