Focal Point Basics Jobsheets

Megawidgets 101

Purpose:

This jobsheet consists of a series of mini exercises designed to build familiarity and experience with creating and modifying megawidgets.

Tasks:

SCOPE: In this jobsheet you'll practice creating your own megawidgets from scratch, and then exploring the ways that their construction can be more sophisticated.  The exact content of the megawidgets is not important, so simple placeholder text is used. Moreover, we need somewhere to create these megawidgets, for which we'll borrow the Hazard Information Dialogue from the HY.O hazard, since it is conveniently blank, and therefore a great place for creating your own megawidgets.

 

TASK 0: Set up the override file, a.k.a. "Prepare your canvas"

  1. In the Localization Perspective, navigate to the Hazard Meta Data sub-directory under the Hazard Services folder.
  2. Double click on MetaData_HY_O.py to show the available versions
  3. Double click on the BASE version of MetaData_HY_O.py to view it
    1. Notice how little code there is... HY.O in fact has nothing in the "Details" section of its HID where MetaData would otherwise be specified. That makes it a great starting point for this exercise
  4. Create a user override version of this file by right-clicking on BASE and selecting Create Override File, then select User
    1. NOTE: We're assuming no USER version already exists
  5. Copy-paste the following code into your USER copy of MetaData_HY_O.py, below the "class..." and "pass" lines
        def execute(self, hazardEvent=None, metaDict=None):
            self.initialize(hazardEvent, metaDict)
            metadata = [#megaWidgetStart
    
                ]#megaWidgetEnd
            return {
                HazardConstants.METADATA_KEY: metadata
                }
    1. NOTE: This is an exact copy of the "execute" method from the base file, with changes highlighted in bold. It introduces a new variable called "metadata", which is just an empty list [ ] for now, which also gets included in the returned dictionary
    2. Make sure you've maintained proper indentation... the "def execute" line should be indented one level more than the "class Metadata" line. If you need to fix your indentation, you can select the whole method, then press TAB to indent everything further, or SHIFT-TAB to remove one level of indentation for the entire selection
  6. When finished, save the file by hitting Ctrl+S, or selecting Save from the File menu
    1. If a "File Version Conflict" is encountered, click OK to accept merge
    2. In the two-panel "Merge" tab that opens, make no changes, once again save the file by hitting Ctrl+s, then close the "Merge" tab
    3. When a "File Changed" message appears,  click Yes.
    4. This behavior will only be encountered each time a new override file that did not exist before is created and saved
  7. Switch to the D2D Perspective and launch Hazard Services
  8. Generate a blank HY.O hazard by following the below steps:
    1. Launch Hazard Services in CAVE
    2. Zoom to WFO Scale in your spatial display
    3. Click the "Drawing Tools" (Pencil icon) on the Hazard Services Toolbar, and select "Draw Polygon"
    4. Draw a polygon in the spatial display by left-clicking to create several vertices and right-clicking to finish
    5. In the HID which appears, select "HY.O (HYDROLOGIC OUTLOOK)" from the Hazard Type drop-down
  9. Take note of the empty space lower down in the HID where the "Details" section would be.
    1. In the coming tasks, we'll begin populating this space with megawidgets

 

TASK 1A: Create a checkbox

  1. Switch back to the Localization Perspective to view your USER copy of MetaData_HY_O.py once again
  2. Type or copy-paste the following code into the USER copy of your file, making sure to insert them between the #megaWidgetStart and #megaWidgetEnd brackets in your code
    {
        "fieldType": "CheckBox",
        "fieldName": "importantCheckBox",
        "label": "Some important item",
        "values": True
    }
    
  3. Make sure you've included proper indentation...
    1. The only true requirement is that all of the above code must be at least as indented as the "metaData" line above it.
    2. Additional indentation within lists and dictionaries (as we see in the megawidget dictionary above) is optional and serves an aesthetic purpose only
    3. To fix the indentation of your inserted code, you may select the lines needing indentation, then press TAB, or SHIFT-TAB to indent or un-indent, respectively.
    4. For reference, a copy of the code as it should appear so far is provided below:
      class MetaData(CommonMetaData.MetaData):
          pass
          def execute(self, hazardEvent=None, metaDict=None):
              self.initialize(hazardEvent, metaDict)
              metadata = [#megaWidgetStart
                      {
                          "fieldType": "CheckBox",
                          "fieldName": "importantCheckBox",
                          "label": "Some important item",
                          "values": True
                      }
                  ]#megaWidgetEnd
              return {
                  HazardConstants.METADATA_KEY: metadata
                  }
  4. Feel free to make any personalized edits to the checkbox properties, using the following tips:
    1. fieldType: DO NOT CHANGE, keep as "CheckBox"
    2. fieldName: Any UNIQUE string for identifying this megawidget
    3. label: Any text you want visible with the megawidget
    4. values: True or False to be default checked or not, respectively
    5. OTHER: Additional properties available to the checkbox can be found here in the megawidget documentation
  5. When finished, save the file by hitting Ctrl+S, or selecting Save from the File menu
  6. Switch back to D2D (or whichever localization you were previously using) to once again view Hazard Services
  7. You can trigger your change to update by restarting Hazard Services or by changing hazard types in the HID and then changing back to HY.O. Click on your HY.O hazard in the Hazard Services console to re-launch the HID. Change the Type: to FF.A and then back to HY.O.​​​​​​
  8. Observe that we now have a "Details" section, and, even more, that there is a checkbox present with your label and properties!
    1. NOTE: Although we've created a megawidget, it hasn't been configured to have any effect yet on product generation via "Preview"

 

TASK 1B: Move the Checkbox megawidget to its own function

Although it was easy to insert a megawidget into the "metadata = [ ]" list in the execute function above, it can get cumbersome maintaining all our megawidgets in this location. All the additional indentation can become a nuisance, and someone looking at the code might not be able to easily tell one megawidget apart from another, as more are added. In this task, we take one approach to remedying this by moving the megawidget code to its own function.(*technically, functions within classes are known as "methods")

  1. Switch back to the Localization Perspective to view your USER copy of MetaData_HY_O.py once again
  2. Create a new method in your USER copy of Metadata_HY_O by typing or copy-pasting the following code at the end of the file:
    def myCheckBox(self):
        return {}
    
    1. Make sure you've maintained proper indentation... the "def myCheckBox" line should be indented to the same level as your "def execute" line. If you need to fix your indentation, you can select the whole method, then press TAB to indent everything further, or SHIFT-TAB to remove one level of indentation for the entire selection
  3. Back in your "execute" method, select the dictionary for the megawidget you previously entered by clicking and dragging from (and including) the opening { bracket immediately before "fieldType", all the way to (and including)  the closing } bracket after the other megawidget properties.
  4. Cut the selected contents by right-clicking and selecting "Cut" from the pop-up menu, or by hitting CTRL-X on your keyboard
  5. Down in your myCheckBox method, replace the empty return dictionary { } with your copied dictionary by selecting the { } brackets, then pasting your clipboard over the { } (right-click and select "Paste" from the pop-up menu, or hit CTRL-V on your keyboard).
    1. Make sure you didn't replace the necessary "return" statement before your dictionary! For reference, your new function should now look similar to the following:
      def myCheckBox(self):
          return {
              "fieldType": "CheckBox",
              "fieldName": "importantCheckBox",
              "label": "Some important item",
              "values": True
          }
  6. (No action in this step) Back again in your "execute" method, you should now have an empty metadata = [ ] list
  7. Where your dictionary used to exist in the execute method (between the opening and closing [ ] brackets of the metadata list variable), type or copy-paste a reference to your new function (new code BOLDED below) so that the metaData list now looks like this
    metadata = [#megaWidgetStart
        self.myCheckBox()
        ]#megaWidgetEnd
    
    1. SYNTAX NOTE: In classes, you refer to methods that are also owned by the class using a "self." prefix before calling the method. Also note that there are no arguments for the myCheckBox method, hence the empty parentheses ( ) in the method call above
  8. You're finished with the needed edits! Proofread for Python syntax mistakes in any areas you edited.
  9. When finished, save the file by hitting Ctrl+S, or selecting Save from the File menu
  10. Switch back to D2D (or whichever localization you were previously using) to once again view Hazard Services
  11. Click on your HY.O hazard in the Hazard Services console to re-launch the HID. Change the Type: to FF.A and then back to HY.O.
  12. Observe that the checkbox is still present, even though we removed it from directly within the Metadata's "execute" function.
    1. [BONUS STEP] To convince yourself that this megawidget is being referenced from the function, go back and edit the megawidget "label" property, then save and check the HID again after changing the hazard type from FF.A to HY.O to see that it updates.
  13. (No action in this step) Reflection... WHY does this matter? 
    1. Readability: As previously mentioned, it is cleaner and easier to identify which megawidgets are being assembled within the "metadata" list of the execute method when they are entered as intuitive function names
    2. Overrides: As its own method in the class, it is MUCH EASIER to precisely target your checkbox megawidget with an override, should you want one in the future. As you become familiar with overrides, you'll appreciate the cleaner division of tasks into their own methods, and justify the overhead of creating and interpreting them
    3. It's Hazard Services Convention: If nothing else, Hazard Services REGULARLY uses this strategy for assembling megawidgets in each hazard's execute function. By going through these steps, you can better understand how Hazard Service distributes its assembly of the HID and other dialogs.

 

TASK 2: Try your own!

Now that you've gotten a little experience with creating megawidgets in Hazard Services, try creating your own! Here are some tips:

  • Keep using the HY.O metadata file we've been modifying above, and check the HID to see what you've created after changing the hazard type to FF.A and back to HY.O. You can try adding the megawidget to the metadata section directly beneath the "self.myCheckBox()," line created above. Once it works there, you can make a separate function as in the example above. Make sure your function "def" entries begin at the same indentation level.
  • Try to stick with the workflow of making a method and referencing it in the metadata list variable, as we practiced in Task 1B.
  • Refer to the very comprehensive documentation (click here) to see what megawidgets you can use, and what unique properties they use.
  • As always, watch out for Python syntax! Feel free to ask for help.