Development Guide

Example - First History

Let's create simple history view for brief demonstration of the history API. (We are going to show history view in our application tab.)

It is possible to do more things using History extension API, see the History guide.

History View Tab

We will extend our app tab to contain pane for history view.

fxml/ExampleAppTab.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import com.warxim.petep.gui.control.SerializedPduView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="645.0" prefWidth="996.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <Label layoutX="10.0" layoutY="10.0" styleClass="heading-2" text="Example Tab" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0" />
      <TabPane layoutY="37.0" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0">
        <tabs>
          <Tab text="History Test">
            <content>
              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                     <children>
                        <AnchorPane fx:id="historyPane" layoutY="36.0" prefHeight="535.0" prefWidth="976.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="35.0" />
                        <Label layoutX="14.0" layoutY="14.0" styleClass="heading-2" text="Here you can see loaded history view:" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0" />
                     </children>
                  </AnchorPane>
            </content>
          </Tab>
          <Tab text="Received serialized PDU">
            <content>
              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                  <Label layoutX="14.0" layoutY="14.0" styleClass="heading-2" text="Last received serialized PDU:" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0" />
                     <SerializedPduView fx:id="serializedPduView" layoutX="10.0" layoutY="34.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="35.0" />
                     <Button fx:id="sendToButton" layoutX="234.0" layoutY="6.0" mnemonicParsing="false" onAction="#onSendToButtonClick" text="Send To" AnchorPane.leftAnchor="200.0" AnchorPane.topAnchor="6.0" />
              </AnchorPane>
            </content>
          </Tab>
        </tabs>
      </TabPane>
    </children>
</AnchorPane>

We will also extend the controller to dynamically load the history view:

gui.ExampleAppTabController
/**
 * Controller for example application tab.
 * <p>Loads history view into the tab content.</p>
 */
@RequiredArgsConstructor
public class ExampleAppTabController implements Initializable {
    private final ExtensionHelper extensionHelper;
    private final HistoryApi historyApi;
    private HistoryView historyView;

    @FXML
    private Pane historyPane;
    @FXML
    private SerializedPduView serializedPduView;
    @FXML
    private Button sendToButton;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        initHistoryView();
        sendToButton.setDisable(true);
    }

    /**
     * Shows serialized PDU in view.
     * @param serializedPdu PDU to be shown
     */
    public void showSerializedPdu(SerializedPdu serializedPdu) {
        sendToButton.setDisable(false);
        serializedPduView.setSerializedPdu(serializedPdu);
    }

    /**
     * Shows dialog for choosing target receiver and then sends serialized PDU to it.
     */
    @FXML
    private void onSendToButtonClick(ActionEvent event) {
        var maybePdu = serializedPduView.getSerializedPdu();
        if (maybePdu.isEmpty()) {
            return;
        }

        // Obtain receivers that support serialized PDU
        var receivers = extensionHelper.getReceivers(SerializedPdu.class).stream()
                .map(ReceiverWrapper::new)
                .collect(Collectors.toList());

        // Let the user pick receiver
        var maybeReceiverWrapper = Dialogs.createChoiceDialog("Send to receiver", "Choose receiver", receivers);
        if (maybeReceiverWrapper.isEmpty()) {
            return;
        }

        // Send the PDU to the receiver
        var receiver = maybeReceiverWrapper.get().getReceiver();
        extensionHelper.sendToReceiver(
                receiver.getCode(),
                maybePdu.get().copy()
        );
    }

    /**
     * Creates and loads history view into the tab.
     */
    private void initHistoryView() {
        if (historyApi == null) {
            return;
        }
        // Create filter for history
        var filter = HistoryFilter.builder().build();

        // Create view to history
        historyView = historyApi.createView(filter);

        // Get JavaFX node of history view
        var historyNode = historyView.getNode();

        AnchorPane.setBottomAnchor(historyNode, 0.0);
        AnchorPane.setTopAnchor(historyNode, 0.0);
        AnchorPane.setLeftAnchor(historyNode, 0.0);
        AnchorPane.setRightAnchor(historyNode, 0.0);

        // Add history node to the history pane
        historyPane.getChildren().add(historyNode);
    }
}

To make this work, we have to get HistoryApi from History extension during load of the application and store reference to it in our extension. For this, we are going to use afterInit method in petep.Extension:

petep.Extension: public void afterInit(ExtensionHelper helper)
var maybeHistory = helper.getExtension("history");
if (maybeHistory.isPresent()) {
    historyApi = (HistoryApi) maybeHistory.get();
}

Now we can hand over the history api reference to our controller by adding it as constructor parameter in initGui:

petep.Extension: public void initGui(GuiHelper helper)
// Load application tab
try {
    var loader = new FXMLLoader(getClass().getResource("/fxml/ExampleAppTab.fxml"));
    var controller = new ExampleAppTabController(extensionHelper, historyApi);
    loader.setController(controller);
    var appTab = (Parent) loader.load();
    receiver.setConsumer(controller::showSerializedPdu);
    helper.registerTab("Example App Tab", appTab);
} catch (IOException e) {
    Logger.getGlobal().log(Level.SEVERE, "Could not load example app tab.", e);
}

After starting PETEP, we should be able to see History in the application tab of our extension.