Commits

Andy Moncsek  committed ae5e57c

package renaming

  • Participants
  • Parent commits c6fc2c8

Comments (0)

Files changed (28)

File JacpFXWebsocketChatClient/pom.xml

                                          uri="javafx:com.sun.javafx.tools.ant" classpathref="maven.plugin.classpath"/>
 
                                 <fx:application id="${project.name}" name="${project.name}"
-                                                mainClass="org.jacp.twitter.main.ApplicationLauncher"
-                                                preloaderClass="org.jacp.twitter.main.ApplicationPreloader"/>
+                                                mainClass="org.jacp.chat.main.ApplicationLauncher"
+                                                preloaderClass="org.jacp.chat.main.ApplicationPreloader"/>
                                 <!-- shrink css to binary; currently uncommented due to http://javafx-jira.kenai.com/browse/RT-21964
                                  <fx:csstobin outdir="${project.build.directory}/classes/styles">
                                     <fileset dir="${project.build.directory}/classes/styles" includes="**/*.css"/>

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/callbacks/WebSocketEndpoint.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [WebSocketEndpoint.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.callbacks;
+
+import javafx.event.Event;
+import org.glassfish.tyrus.client.ClientManager;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.CallbackComponent;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AStatefulCallbackComponent;
+import org.jacp.jee.messages.ChatMessage;
+import org.jacp.jee.messages.LoginMessage;
+import org.jacp.jee.messages.Message;
+import org.jacp.jee.messages.UserAddMessage;
+import org.jacp.chat.decoders.MessageDecoder;
+import org.jacp.chat.encoders.ChatMessageEncoder;
+import org.jacp.chat.encoders.ClientLoginEncoder;
+
+import javax.websocket.*;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+
+/**
+ * A Stateful JacpFX component.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@CallbackComponent(id = "id003", name = "statefulCallback", active = false)
+@ClientEndpoint(encoders = {ClientLoginEncoder.class, ChatMessageEncoder.class}, decoders = {MessageDecoder.class})
+public class WebSocketEndpoint extends AStatefulCallbackComponent {
+    private Session session;
+    private CountDownLatch messageLatch = new CountDownLatch(1);
+    private final Logger log = Logger.getLogger(WebSocketEndpoint.class
+            .getName());
+
+    @Override
+    public Object handleAction(final IAction<Event, Object> arg0) {
+        if (arg0.getLastMessage() instanceof LoginMessage) {
+            login((LoginMessage) arg0.getLastMessage());
+        } else if (arg0.getLastMessage() instanceof ChatMessage) {
+            sendMessage((ChatMessage) arg0.getLastMessage());
+        }
+        return null;
+    }
+
+    /**
+     * send login to endpoint
+     *
+     * @param message
+     */
+    public void login(LoginMessage message) {
+        try {
+            session.getBasicRemote().sendObject(message);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (EncodeException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * Send websocket message
+     *
+     * @param message
+     */
+    public void sendMessage(ChatMessage message) {
+        try {
+            session.getBasicRemote().sendObject(message);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (EncodeException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    @OnStart
+    public void init() {
+        this.log.info("WebSocketEndpoint start");
+        ClientManager client = ClientManager.createClient();
+        // authentication example
+       /* try {
+            ClientEndpointConfig config =                        ClientEndpointConfig.Builder.create().configurator(new ClientEndpointConfig.Configurator() {
+                @Override
+                public void beforeRequest(Map<String, List<String>> headers) {
+                    byte[] encodedPassword = ( userName + ":" + password ).getBytes();
+                    BASE64Encoder encoder = new BASE64Encoder();
+                    headers.put("Authorization",
+                            Arrays.asList("Basic " + encoder.encode( encodedPassword )));
+                }
+            }).build();*/
+        try {
+            session = client.connectToServer(this, ClientEndpointConfig.Builder.create().build(), getURI());
+            messageLatch.await(5, TimeUnit.SECONDS);
+        } catch (DeploymentException e) {
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @OnOpen
+    public void onOpen(Session session) {
+        this.session = session;
+        messageLatch.countDown();
+    }
+
+    @OnMessage
+    public void onChatMessage(Message chatMessage) {
+        switch (chatMessage.getType()){
+            case MESSAGE:
+                ChatMessage message = (ChatMessage) chatMessage;
+                log.info("twitter message: " + message.getMessage());
+                this.getActionListener("id002", message).performAction(null);
+                break;
+            case ADD_USER:
+                UserAddMessage userAdd = (UserAddMessage) chatMessage;
+                log.info("user added: " + userAdd.getUserName());
+                this.getActionListener("id001", userAdd).performAction(null);
+                break;
+        }
+
+    }
+
+
+    @OnTearDown
+    public void cleanup() {
+        this.log.info("WebSocketEndpoint stop");
+        try {
+            session.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private URI getURI() {
+        try {
+            return new URI("ws", null, "localhost", 8080, "/WebClient-Websocket/twitter", null, null);
+        } catch (URISyntaxException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/components/ChatView.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [ComponentRight.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.components;
+
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.DeclarativeComponent;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AFXComponent;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.components.managedDialog.JACPManagedDialog;
+import org.jacp.javafx.rcp.components.managedDialog.ManagedDialogHandler;
+import org.jacp.javafx.rcp.components.modalDialog.JACPModalDialog;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+import org.jacp.jee.messages.ChatMessage;
+import org.jacp.jee.messages.LoginMessage;
+import org.jacp.chat.dialogs.LoginDialog;
+import org.jacp.chat.entities.User;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.ResourceBundle;
+import java.util.logging.Logger;
+
+/**
+ * A simple JacpFX FXML UI component
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@DeclarativeComponent(defaultExecutionTarget = "PMain", id = "id002", name = "componentRight", active = true, viewLocation = "/fxml/ComponentRightFXML.fxml", resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
+public class ChatView extends AFXComponent {
+
+    private final Logger log = Logger.getLogger(ChatView.class
+            .getName());
+    @FXML
+    private TextField message;
+
+    @FXML
+    private TextArea descriptionValue;
+
+    private User currentUser;
+
+    @Override
+    /**
+     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
+     */
+    public Node handleAction(final IAction<Event, Object> action) {
+        if (action.getLastMessage() instanceof LoginMessage) {
+            LoginMessage user = (LoginMessage) action.getLastMessage();
+            currentUser = new User(user.getUserName());
+        }
+        return null;
+    }
+
+    @Override
+    /**
+     * The postHandleAction method runs always in the main application thread.
+     */
+    public Node postHandleAction(final Node arg0,
+                                 final IAction<Event, Object> action) {
+        // runs in FX application thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            ManagedDialogHandler<LoginDialog> handler = JACPManagedDialog.getInstance().getManagedDialog(
+                    LoginDialog.class);
+            JACPModalDialog.getInstance().showModalMessage(handler.getDialogNode());
+        } else if (action.getLastMessage() instanceof ChatMessage) {
+            ChatMessage message = (ChatMessage) action.getLastMessage();
+            String current = descriptionValue.getText();
+            String updatedText = current.concat("\n")
+                    .concat(DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date()))
+                    .concat(" : ").concat(message.getUserName()).concat(": ").concat(message.getMessage());
+            descriptionValue.setText(updatedText);
+        }
+        return null;
+    }
+
+    @OnStart
+    /**
+     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
+     * @param arg0
+     * @param resourceBundle
+     */
+    public void onStartComponent(final FXComponentLayout arg0,
+                                 final ResourceBundle resourceBundle) {
+        this.log.info("run on start of ComponentRight ");
+
+    }
+
+    @OnTearDown
+    /**
+     * The @OnTearDown annotations labels methods executed when the component is set to inactive
+     * @param arg0
+     */
+    public void onTearDownComponent(final FXComponentLayout arg0) {
+        this.log.info("run on tear down of ComponentRight ");
+
+    }
+
+
+    @FXML
+    private void handleSend(final ActionEvent event) {
+        String messageText = message.getText();
+        this.getActionListener("id003", new ChatMessage(currentUser.getUserName(), messageText))
+                .performAction(null);
+        message.setText("");
+    }
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/components/UserView.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [UserView.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.components;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import javafx.event.Event;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.*;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.AnchorPaneBuilder;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import javafx.util.Callback;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.Component;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AFXComponent;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+import org.jacp.jee.messages.UserAddMessage;
+import org.jacp.chat.entities.User;
+
+import java.util.ResourceBundle;
+import java.util.logging.Logger;
+
+/**
+ * A simple JacpFX UI component
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@Component(defaultExecutionTarget = "Pleft", id = "id001", name = "componentLeft", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
+public class UserView extends AFXComponent {
+    private AnchorPane pane;
+    private ObservableList<User> users = FXCollections.observableArrayList();
+    private final Logger log = Logger.getLogger(UserView.class.getName());
+
+
+    @Override
+    /**
+     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
+     */
+    public Node handleAction(final IAction<Event, Object> action) {
+        // runs in worker thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            return this.createUI();
+        } else if (action.getLastMessage() instanceof UserAddMessage) {
+            UserAddMessage user = (UserAddMessage) action.getLastMessage();
+            users.add(new User(user.getUserName()));
+        }
+        return null;
+    }
+
+    @Override
+    /**
+     * The postHandleAction method runs always in the main application thread.
+     */
+    public Node postHandleAction(final Node arg0,
+                                 final IAction<Event, Object> action) {
+        // runs in FX application thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            this.pane = (AnchorPane) arg0;
+        }
+        return this.pane;
+    }
+
+    @OnStart
+    /**
+     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
+     * @param arg0
+     */
+    public void onStartComponent(final FXComponentLayout arg0,
+                                 final ResourceBundle resourceBundle) {
+        this.log.info("run on start of UserView ");
+    }
+
+    @OnTearDown
+    /**
+     * The @OnTearDown annotations labels methods executed when the component is set to inactive
+     * @param arg0
+     */
+    public void onTearDownComponent(final FXComponentLayout arg0) {
+        this.log.info("run on tear down of UserView ");
+
+    }
+
+    /**
+     * create the UI on first call
+     *
+     * @return
+     */
+    private Node createUI() {
+        final AnchorPane anchor = AnchorPaneBuilder.create()
+                .styleClass("roundedAnchorPaneFX").build();
+        final Label heading = LabelBuilder.create()
+                .text(this.getResourceBundle().getString("registeredUsers"))
+                .alignment(Pos.CENTER_RIGHT).styleClass("propLabelBig").build();
+
+        final TreeItem<User> rootNode =
+                new TreeItem<User>(new User("----"));
+        final TreeView<User> treeView = new TreeView<User>(rootNode);
+        users.addListener(new ListChangeListener<User>() {
+            @Override
+            public void onChanged(Change<? extends User> change) {
+                rootNode.getChildren().clear();
+                if (change == null) return;
+                for (User u : change.getList()) {
+                    rootNode.getChildren().add(new TreeItem<>(u));
+                }
+            }
+        });
+        treeView.setShowRoot(false);
+        treeView.setCellFactory(new Callback<TreeView<User>, TreeCell<User>>() {
+            @Override
+            public TreeCell<User> call(TreeView<User> userTreeView) {
+                return new TreeCell<User>() {
+                    @Override
+                    public void updateItem(User item, boolean empty) {
+                        super.updateItem(item, empty);
+                        if (!empty) {
+                            setText(item.getUserName());
+                            setGraphic(getTreeItem().getGraphic());
+                        }
+                    }
+                };
+            }
+        });
+        AnchorPane.setRightAnchor(heading, 40.0);
+        AnchorPane.setTopAnchor(heading, 15.0);
+
+
+        AnchorPane.setTopAnchor(treeView, 50.0);
+        AnchorPane.setRightAnchor(treeView, 25.0);
+        AnchorPane.setLeftAnchor(treeView, 25.0);
+
+        anchor.getChildren().addAll(heading, treeView);
+
+        GridPane.setHgrow(anchor, Priority.ALWAYS);
+        GridPane.setVgrow(anchor, Priority.ALWAYS);
+
+        return anchor;
+    }
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/decoders/MessageDecoder.java

+/*
+ * Copyright (c) 2013, Andy Moncsek, inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ *    the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
+ *    promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jacp.chat.decoders;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.jacp.jee.messages.Message;
+
+import javax.websocket.DecodeException;
+import javax.websocket.Decoder;
+import javax.websocket.EndpointConfig;
+import java.nio.ByteBuffer;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Andy Moncsek
+ * Date: 27.02.13
+ * Time: 15:32
+ * To change this template use File | Settings | File Templates.
+ */
+public class MessageDecoder implements Decoder.Binary<Message> {
+    @Override
+    public Message decode(ByteBuffer byteBuffer) throws DecodeException {
+        return (Message) SerializationUtils.deserialize(byteBuffer.array());  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean willDecode(ByteBuffer byteBuffer) {
+        Object message = SerializationUtils.deserialize(byteBuffer.array());
+        if (message == null) return false;
+        return message instanceof Message;
+    }
+
+    @Override
+    public void init(EndpointConfig endpointConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void destroy() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
+
+

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/dialogs/LoginDialog.java

+package org.jacp.chat.dialogs;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+import org.jacp.api.annotations.Dialog;
+import org.jacp.api.annotations.Resource;
+import org.jacp.api.dialog.Scope;
+import org.jacp.javafx.rcp.component.AFXComponent;
+import org.jacp.javafx.rcp.components.modalDialog.JACPModalDialog;
+import org.jacp.jee.messages.LoginMessage;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Andy moncsek
+ * Date: 06.03.13
+ * Time: 15:43
+ * To change this template use File | Settings | File Templates.
+ */
+@Dialog(id = "id100", viewLocation = "/fxml/LoginDialog.fxml", resourceBundleLocation = "bundles.languageBundle", localeID = "en_US", scope = Scope.SINGLETON)
+public class LoginDialog {
+
+    @FXML
+    private TextField login;
+    @Resource
+    private AFXComponent parent;
+
+    @FXML
+    public void login() {
+        if (login.getText() != null && !login.getText().isEmpty()) {
+            parent.getActionListener("id003", new LoginMessage(login.getText())).performAction(null);
+            parent.getActionListener("id002", new LoginMessage(login.getText())).performAction(null);
+            JACPModalDialog.getInstance().hideModalMessage();
+        }
+
+    }
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/encoders/ChatMessageEncoder.java

+package org.jacp.chat.encoders;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.jacp.jee.messages.ChatMessage;
+
+import javax.websocket.EncodeException;
+import javax.websocket.Encoder;
+import javax.websocket.EndpointConfig;
+import java.nio.ByteBuffer;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 06.03.13
+ * Time: 10:14
+ * To change this template use File | Settings | File Templates.
+ */
+public class ChatMessageEncoder implements Encoder.Binary<ChatMessage> {
+    @Override
+    public ByteBuffer encode(ChatMessage message) throws EncodeException {
+        return ByteBuffer.wrap(SerializationUtils.serialize(message));
+    }
+
+    @Override
+    public void init(EndpointConfig endpointConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void destroy() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/encoders/ClientLoginEncoder.java

+package org.jacp.chat.encoders;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.jacp.jee.messages.LoginMessage;
+
+import javax.websocket.EncodeException;
+import javax.websocket.Encoder;
+import javax.websocket.EndpointConfig;
+import java.nio.ByteBuffer;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 28.02.13
+ * Time: 09:50
+ * To change this template use File | Settings | File Templates.
+ */
+public class ClientLoginEncoder  implements Encoder.Binary<LoginMessage> {
+    @Override
+    public ByteBuffer encode(LoginMessage loginMessage) throws EncodeException {
+        return ByteBuffer.wrap(SerializationUtils.serialize(loginMessage));
+    }
+
+    @Override
+    public void init(EndpointConfig endpointConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void destroy() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/entities/User.java

+package org.jacp.chat.entities;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 06.03.13
+ * Time: 11:48
+ * To change this template use File | Settings | File Templates.
+ */
+public class User {
+    private final String userName;
+
+    public User(final String userName) {
+        this.userName = userName;
+    }
+
+    public String getUserName() {
+        return this.userName;
+    }
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/main/ApplicationLauncher.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [ApplicationLauncher.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.main;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.image.Image;
+import javafx.stage.Stage;
+import org.jacp.project.launcher.AFXSpringLauncher;
+
+import java.net.URL;
+import java.util.logging.Logger;
+
+/**
+ * The application launcher containing the main method
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class ApplicationLauncher extends AFXSpringLauncher {
+    private static final Logger log = Logger.getLogger(ApplicationLauncher.class
+            .getName());
+    public static final String[] STYLES = new String[2];
+    private static final String[] STYLE_FILES = {"/styles/style_light.css", "/styles/style_dark.css"};
+    /// binary style sheets created while deployment
+    private static final String[] BINARY_FILES = {"/styles/style_light.bss", "/styles/style_dark.bss"};
+
+    public ApplicationLauncher() {
+        super("main.xml");
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(final String[] args) {
+        Application.launch(args);
+    }
+
+    @Override
+    public void postInit(final Stage stage) {
+        initStyles();
+        stage.setMinHeight(580);
+        stage.setMinWidth(800);
+        final Scene scene = stage.getScene();
+        stage.getIcons().add(new Image("images/icons/JACP_512_512.png"));
+        // add style sheet
+        scene.getStylesheets().add(STYLES[0]);
+    }
+
+    private static void initStyles() {
+        for (int i = 0; i < 2; i++) {
+            URL res = ApplicationLauncher.class.getResource(BINARY_FILES[i]);
+            if (res == null)
+                res = ApplicationLauncher.class.getResource(STYLE_FILES[i]);
+            STYLES[i] = res.toExternalForm();
+            log.info("found: " + STYLES[i] + " stylesheet");
+        }
+
+    }
+
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/main/ApplicationPreloader.java

+package org.jacp.chat.main;
+
+import javafx.animation.FadeTransition;
+import javafx.application.Preloader;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.Scene;
+import javafx.scene.control.ProgressBar;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.BorderPaneBuilder;
+import javafx.stage.Stage;
+import javafx.util.Duration;
+
+/**
+ * The application Preloader. It is just a simple splash screen on application
+ * init. The preloader shows up only when execute the package.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class ApplicationPreloader extends Preloader {
+    private ProgressBar bar;
+    private Stage stage;
+    private boolean isEmbedded = false;
+
+    public void start(Stage stage) throws Exception {
+        isEmbedded = (stage.getWidth() > 0);
+        this.stage = stage;
+        stage.setScene(createPreloaderScene());
+        stage.show();
+    }
+
+    @Override
+    public void handleProgressNotification(ProgressNotification pn) {
+        bar.setProgress(pn.getProgress());
+    }
+
+    @Override
+    public void handleStateChangeNotification(StateChangeNotification evt) {
+        if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
+            if (isEmbedded && stage.isShowing()) {
+                // fade out, hide stage at the end of animation
+                final FadeTransition ft = new FadeTransition(
+                        Duration.millis(3000), stage.getScene().getRoot());
+                ft.setFromValue(1.0);
+                ft.setToValue(0.0);
+                final Stage s = stage;
+                final EventHandler<ActionEvent> eh = new EventHandler<ActionEvent>() {
+                    public void handle(ActionEvent t) {
+                        s.hide();
+                    }
+                };
+                ft.setOnFinished(eh);
+                ft.play();
+            } else {
+                stage.hide();
+            }
+        }
+    }
+
+    private Scene createPreloaderScene() {
+        bar = new ProgressBar();
+        final BorderPane p = BorderPaneBuilder
+                .create()
+                .center(new ImageView(new Image(this.getClass()
+                        .getResourceAsStream("/images/jacp-splash.png"))))
+                .bottom(bar).build();
+        return new Scene(p, 412, 279);
+    }
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/main/Paint.java

+package org.jacp.chat.main;
+
+import javafx.application.Application;
+import javafx.event.EventHandler;
+import javafx.scene.Group;
+import javafx.scene.Scene;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.LineTo;
+import javafx.scene.shape.MoveTo;
+import javafx.scene.shape.Path;
+import javafx.stage.Stage;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 07.03.13
+ * Time: 14:28
+ * To change this template use File | Settings | File Templates.
+ */
+public class Paint extends Application {
+    Path path;
+
+    public static void main(String[] args) {
+        launch(args);
+    }
+
+    @Override
+    public void start(Stage primaryStage) {
+        Group root = new Group();
+        Scene scene = new Scene(root, 300, 250);
+
+        path = new Path();
+        path.setStrokeWidth(1);
+        path.setStroke(Color.BLACK);
+
+        scene.setOnMouseClicked(mouseHandler);
+        scene.setOnMouseDragged(mouseHandler);
+        scene.setOnMouseEntered(mouseHandler);
+        scene.setOnMouseExited(mouseHandler);
+        scene.setOnMouseMoved(mouseHandler);
+        scene.setOnMousePressed(mouseHandler);
+        scene.setOnMouseReleased(mouseHandler);
+
+        root.getChildren().add(path);
+        primaryStage.setScene(scene);
+        primaryStage.show();
+    }
+
+    EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
+
+        @Override
+        public void handle(MouseEvent mouseEvent) {
+            if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
+                path.getElements().clear();
+                path.getElements()
+                        .add(new MoveTo(mouseEvent.getX(), mouseEvent.getY()));
+            } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
+                System.out.println(mouseEvent.getX() + " : " + mouseEvent.getY());
+                path.getElements()
+                        .add(new LineTo(mouseEvent.getX(), mouseEvent.getY()));
+            }
+
+        }
+
+    };
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/perspectives/PerspectiveOne.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [PerspectiveOne.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.perspectives;
+
+import javafx.event.Event;
+import javafx.fxml.FXML;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.api.annotations.Perspective;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.componentLayout.PerspectiveLayout;
+import org.jacp.javafx.rcp.perspective.AFXPerspective;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+
+import java.util.ResourceBundle;
+
+/**
+ * A simple perspective defining a split pane
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@Perspective(id = "id01", name = "perspectiveOne", viewLocation = "/fxml/perspectiveOne.fxml", resourceBundleLocation = "bundles.languageBundle")
+public class PerspectiveOne extends AFXPerspective {
+    @FXML
+    private GridPane gridPaneLeft;
+    @FXML
+    private GridPane gridPaneRight;
+
+    @Override
+    public void handlePerspective(final IAction<Event, Object> action,
+                                  final PerspectiveLayout perspectiveLayout) {
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+
+            GridPane.setVgrow(perspectiveLayout.getRootComponent(),
+                    Priority.ALWAYS);
+            GridPane.setHgrow(perspectiveLayout.getRootComponent(),
+                    Priority.ALWAYS);
+
+            // register left panel
+            perspectiveLayout.registerTargetLayoutComponent("Pleft",
+                    this.gridPaneLeft);
+            // register main panel
+            perspectiveLayout.registerTargetLayoutComponent("PMain",
+                    this.gridPaneRight);
+
+        }
+
+    }
+
+    @OnStart
+    /**
+     * @OnStart annotated method will be executed when component is activated.
+     * @param layout
+     * @param resourceBundle
+     */
+    public void onStartPerspective(final FXComponentLayout layout,
+                                   final ResourceBundle resourceBundle) {
+
+    }
+
+    @OnTearDown
+    /**
+     * @OnTearDown annotated method will be executed when component is deactivated.
+     * @param arg0
+     */
+    public void onTearDownPerspective(final FXComponentLayout arg0) {
+        // remove toolbars and menu entries when close perspective
+
+    }
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/chat/workbench/Workbench.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [Workbench.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.chat.workbench;
+
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuItem;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+import org.jacp.api.action.IAction;
+import org.jacp.api.componentLayout.IWorkbenchLayout;
+import org.jacp.chat.main.ApplicationLauncher;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.components.menuBar.JACPMenuBar;
+import org.jacp.javafx.rcp.components.modalDialog.JACPModalDialog;
+import org.jacp.javafx.rcp.controls.optionPane.JACPDialogButton;
+import org.jacp.javafx.rcp.controls.optionPane.JACPDialogUtil;
+import org.jacp.javafx.rcp.controls.optionPane.JACPOptionPane;
+import org.jacp.javafx.rcp.workbench.AFXWorkbench;
+
+/**
+ * A simple JacpFX workbench. Define basic UI settings like size, menus and
+ * toolbars here.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class Workbench extends AFXWorkbench {
+    private Stage stage;
+
+    @Override
+    public void handleInitialLayout(final IAction<Event, Object> action,
+                                    final IWorkbenchLayout<Node> layout, final Stage stage) {
+        layout.setWorkbenchXYSize(1024, 600);
+        layout.setStyle(StageStyle.DECORATED);
+        layout.setMenuEnabled(true);
+        this.stage = stage;
+
+    }
+
+    @Override
+    public void postHandle(final FXComponentLayout layout) {
+        final JACPMenuBar menu = layout.getMenu();
+        final Menu menuFile = new Menu("File");
+        final Menu menuStyles = new Menu("Styles");
+        menuFile.getItems().add(getHelpItem());
+        // add style selection
+        for (int i = 0; i < ApplicationLauncher.STYLES.length; i++) {
+            menuStyles.getItems().add(getStyle(i));
+        }
+
+        menu.getMenus().addAll(menuFile, menuStyles);
+
+
+        // show windowButtons
+        menu.registerWindowButtons();
+    }
+
+
+    private MenuItem getStyle(final int count) {
+        final MenuItem itemHelp = new MenuItem(count == 0 ? "Light" : "Dark");
+        itemHelp.setOnAction(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(final ActionEvent arg0) {
+                final Scene scene = Workbench.this.stage.getScene();
+                // index 0 is always the default JACP style
+                scene.getStylesheets().remove(1);
+                scene.getStylesheets().add(ApplicationLauncher.STYLES[count]);
+
+            }
+        });
+        return itemHelp;
+    }
+
+    private MenuItem getHelpItem() {
+        final MenuItem itemHelp = new MenuItem("Help");
+        itemHelp.setOnAction(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(final ActionEvent arg0) {
+                // create a modal dialog
+                final JACPOptionPane dialog = JACPDialogUtil.createOptionPane(
+                        "Help", "Add some help text ");
+                dialog.setDefaultButton(JACPDialogButton.NO);
+                dialog.setDefaultCloseButtonOrientation(Pos.CENTER_RIGHT);
+                dialog.setOnYesAction(new EventHandler<ActionEvent>() {
+
+                    @Override
+                    public void handle(final ActionEvent arg0) {
+                        JACPModalDialog.getInstance().hideModalMessage();
+                    }
+                });
+                JACPModalDialog.getInstance().showModalMessage(dialog);
+
+            }
+        });
+        return itemHelp;
+    }
+
+}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/twitter/callbacks/WebSocketEndpoint.java

-/************************************************************************
- *
- * Copyright (C) 2010 - 2012
- *
- * [WebSocketEndpoint.java]
- * AHCP Project (http://jacp.googlecode.com)
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an "AS IS"
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
- * express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- *
- *
- ************************************************************************/
-package org.jacp.twitter.callbacks;
-
-import javafx.event.Event;
-import org.glassfish.tyrus.client.ClientManager;
-import org.jacp.api.action.IAction;
-import org.jacp.api.annotations.CallbackComponent;
-import org.jacp.api.annotations.OnStart;
-import org.jacp.api.annotations.OnTearDown;
-import org.jacp.javafx.rcp.component.AStatefulCallbackComponent;
-import org.jacp.jee.messages.ChatMessage;
-import org.jacp.jee.messages.LoginMessage;
-import org.jacp.jee.messages.Message;
-import org.jacp.jee.messages.UserAddMessage;
-import org.jacp.twitter.decoders.MessageDecoder;
-import org.jacp.twitter.encoders.ChatMessageEncoder;
-import org.jacp.twitter.encoders.ClientLoginEncoder;
-import sun.misc.BASE64Encoder;
-
-import javax.websocket.*;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Logger;
-
-
-/**
- * A Stateful JacpFX component.
- *
- * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
- */
-@CallbackComponent(id = "id003", name = "statefulCallback", active = false)
-@ClientEndpoint(encoders = {ClientLoginEncoder.class, ChatMessageEncoder.class}, decoders = {MessageDecoder.class})
-public class WebSocketEndpoint extends AStatefulCallbackComponent {
-    private Session session;
-    private CountDownLatch messageLatch = new CountDownLatch(1);
-    private final Logger log = Logger.getLogger(WebSocketEndpoint.class
-            .getName());
-
-    @Override
-    public Object handleAction(final IAction<Event, Object> arg0) {
-        if (arg0.getLastMessage() instanceof LoginMessage) {
-            login((LoginMessage) arg0.getLastMessage());
-        } else if (arg0.getLastMessage() instanceof ChatMessage) {
-            sendMessage((ChatMessage) arg0.getLastMessage());
-        }
-        return null;
-    }
-
-    /**
-     * send login to endpoint
-     *
-     * @param message
-     */
-    public void login(LoginMessage message) {
-        try {
-            session.getBasicRemote().sendObject(message);
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (EncodeException e) {
-            e.printStackTrace();
-        }
-
-    }
-
-    /**
-     * Send websocket message
-     *
-     * @param message
-     */
-    public void sendMessage(ChatMessage message) {
-        try {
-            session.getBasicRemote().sendObject(message);
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (EncodeException e) {
-            e.printStackTrace();
-        }
-
-    }
-
-    @OnStart
-    public void init() {
-        this.log.info("WebSocketEndpoint start");
-        ClientManager client = ClientManager.createClient();
-        // authentication example
-       /* try {
-            ClientEndpointConfig config =                        ClientEndpointConfig.Builder.create().configurator(new ClientEndpointConfig.Configurator() {
-                @Override
-                public void beforeRequest(Map<String, List<String>> headers) {
-                    byte[] encodedPassword = ( userName + ":" + password ).getBytes();
-                    BASE64Encoder encoder = new BASE64Encoder();
-                    headers.put("Authorization",
-                            Arrays.asList("Basic " + encoder.encode( encodedPassword )));
-                }
-            }).build();*/
-        try {
-            session = client.connectToServer(this, ClientEndpointConfig.Builder.create().build(), getURI());
-            messageLatch.await(5, TimeUnit.SECONDS);
-        } catch (DeploymentException e) {
-            e.printStackTrace();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-    }
-
-    @OnOpen
-    public void onOpen(Session session) {
-        this.session = session;
-        messageLatch.countDown();
-    }
-
-    @OnMessage
-    public void onChatMessage(Message chatMessage) {
-        switch (chatMessage.getType()){
-            case MESSAGE:
-                ChatMessage message = (ChatMessage) chatMessage;
-                log.info("twitter message: " + message.getMessage());
-                this.getActionListener("id002", message).performAction(null);
-                break;
-            case ADD_USER:
-                UserAddMessage userAdd = (UserAddMessage) chatMessage;
-                log.info("user added: " + userAdd.getUserName());
-                this.getActionListener("id001", userAdd).performAction(null);
-                break;
-        }
-
-    }
-
-
-    @OnTearDown
-    public void cleanup() {
-        this.log.info("WebSocketEndpoint stop");
-        try {
-            session.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private URI getURI() {
-        try {
-            return new URI("ws", null, "localhost", 8080, "/WebClient-Websocket/twitter", null, null);
-        } catch (URISyntaxException e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/twitter/components/ChatView.java

-/************************************************************************
- *
- * Copyright (C) 2010 - 2012
- *
- * [ComponentRight.java]
- * AHCP Project (http://jacp.googlecode.com)
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an "AS IS"
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
- * express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- *
- *
- ************************************************************************/
-package org.jacp.twitter.components;
-
-import javafx.event.ActionEvent;
-import javafx.event.Event;
-import javafx.fxml.FXML;
-import javafx.scene.Node;
-import javafx.scene.control.TextArea;
-import javafx.scene.control.TextField;
-import org.jacp.api.action.IAction;
-import org.jacp.api.annotations.DeclarativeComponent;
-import org.jacp.api.annotations.OnStart;
-import org.jacp.api.annotations.OnTearDown;
-import org.jacp.javafx.rcp.component.AFXComponent;
-import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
-import org.jacp.javafx.rcp.components.managedDialog.JACPManagedDialog;
-import org.jacp.javafx.rcp.components.managedDialog.ManagedDialogHandler;
-import org.jacp.javafx.rcp.components.modalDialog.JACPModalDialog;
-import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
-import org.jacp.jee.messages.ChatMessage;
-import org.jacp.jee.messages.LoginMessage;
-import org.jacp.twitter.dialogs.LoginDialog;
-import org.jacp.twitter.entities.User;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.ResourceBundle;
-import java.util.logging.Logger;
-
-/**
- * A simple JacpFX FXML UI component
- *
- * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
- */
-@DeclarativeComponent(defaultExecutionTarget = "PMain", id = "id002", name = "componentRight", active = true, viewLocation = "/fxml/ComponentRightFXML.fxml", resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
-public class ChatView extends AFXComponent {
-
-    private final Logger log = Logger.getLogger(ChatView.class
-            .getName());
-    @FXML
-    private TextField message;
-
-    @FXML
-    private TextArea descriptionValue;
-
-    private User currentUser;
-
-    @Override
-    /**
-     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
-     */
-    public Node handleAction(final IAction<Event, Object> action) {
-        if (action.getLastMessage() instanceof LoginMessage) {
-            LoginMessage user = (LoginMessage) action.getLastMessage();
-            currentUser = new User(user.getUserName());
-        }
-        return null;
-    }
-
-    @Override
-    /**
-     * The postHandleAction method runs always in the main application thread.
-     */
-    public Node postHandleAction(final Node arg0,
-                                 final IAction<Event, Object> action) {
-        // runs in FX application thread
-        if (action.getLastMessage().equals(MessageUtil.INIT)) {
-            ManagedDialogHandler<LoginDialog> handler = JACPManagedDialog.getInstance().getManagedDialog(
-                    LoginDialog.class);
-            JACPModalDialog.getInstance().showModalMessage(handler.getDialogNode());
-        } else if (action.getLastMessage() instanceof ChatMessage) {
-            ChatMessage message = (ChatMessage) action.getLastMessage();
-            String current = descriptionValue.getText();
-            String updatedText = current.concat("\n")
-                    .concat(DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date()))
-                    .concat(" : ").concat(message.getUserName()).concat(": ").concat(message.getMessage());
-            descriptionValue.setText(updatedText);
-        }
-        return null;
-    }
-
-    @OnStart
-    /**
-     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
-     * @param arg0
-     * @param resourceBundle
-     */
-    public void onStartComponent(final FXComponentLayout arg0,
-                                 final ResourceBundle resourceBundle) {
-        this.log.info("run on start of ComponentRight ");
-
-    }
-
-    @OnTearDown
-    /**
-     * The @OnTearDown annotations labels methods executed when the component is set to inactive
-     * @param arg0
-     */
-    public void onTearDownComponent(final FXComponentLayout arg0) {
-        this.log.info("run on tear down of ComponentRight ");
-
-    }
-
-
-    @FXML
-    private void handleSend(final ActionEvent event) {
-        String messageText = message.getText();
-        this.getActionListener("id003", new ChatMessage(currentUser.getUserName(), messageText))
-                .performAction(null);
-        message.setText("");
-    }
-
-}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/twitter/components/UserView.java

-/************************************************************************
- *
- * Copyright (C) 2010 - 2012
- *
- * [UserView.java]
- * AHCP Project (http://jacp.googlecode.com)
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an "AS IS"
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
- * express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- *
- *
- ************************************************************************/
-package org.jacp.twitter.components;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
-import javafx.collections.ObservableList;
-import javafx.event.Event;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.layout.AnchorPane;
-import javafx.scene.layout.AnchorPaneBuilder;
-import javafx.scene.layout.GridPane;
-import javafx.scene.layout.Priority;
-import javafx.util.Callback;
-import org.jacp.api.action.IAction;
-import org.jacp.api.annotations.Component;
-import org.jacp.api.annotations.OnStart;
-import org.jacp.api.annotations.OnTearDown;
-import org.jacp.javafx.rcp.component.AFXComponent;
-import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
-import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
-import org.jacp.jee.messages.UserAddMessage;
-import org.jacp.twitter.entities.User;
-
-import java.util.ResourceBundle;
-import java.util.logging.Logger;
-
-/**
- * A simple JacpFX UI component
- *
- * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
- */
-@Component(defaultExecutionTarget = "Pleft", id = "id001", name = "componentLeft", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
-public class UserView extends AFXComponent {
-    private AnchorPane pane;
-    private ObservableList<User> users = FXCollections.observableArrayList();
-    private final Logger log = Logger.getLogger(UserView.class.getName());
-
-
-    @Override
-    /**
-     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
-     */
-    public Node handleAction(final IAction<Event, Object> action) {
-        // runs in worker thread
-        if (action.getLastMessage().equals(MessageUtil.INIT)) {
-            return this.createUI();
-        } else if (action.getLastMessage() instanceof UserAddMessage) {
-            UserAddMessage user = (UserAddMessage) action.getLastMessage();
-            users.add(new User(user.getUserName()));
-        }
-        return null;
-    }
-
-    @Override
-    /**
-     * The postHandleAction method runs always in the main application thread.
-     */
-    public Node postHandleAction(final Node arg0,
-                                 final IAction<Event, Object> action) {
-        // runs in FX application thread
-        if (action.getLastMessage().equals(MessageUtil.INIT)) {
-            this.pane = (AnchorPane) arg0;
-        }
-        return this.pane;
-    }
-
-    @OnStart
-    /**
-     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
-     * @param arg0
-     */
-    public void onStartComponent(final FXComponentLayout arg0,
-                                 final ResourceBundle resourceBundle) {
-        this.log.info("run on start of UserView ");
-    }
-
-    @OnTearDown
-    /**
-     * The @OnTearDown annotations labels methods executed when the component is set to inactive
-     * @param arg0
-     */
-    public void onTearDownComponent(final FXComponentLayout arg0) {
-        this.log.info("run on tear down of UserView ");
-
-    }
-
-    /**
-     * create the UI on first call
-     *
-     * @return
-     */
-    private Node createUI() {
-        final AnchorPane anchor = AnchorPaneBuilder.create()
-                .styleClass("roundedAnchorPaneFX").build();
-        final Label heading = LabelBuilder.create()
-                .text(this.getResourceBundle().getString("registeredUsers"))
-                .alignment(Pos.CENTER_RIGHT).styleClass("propLabelBig").build();
-
-        final TreeItem<User> rootNode =
-                new TreeItem<User>(new User("----"));
-        final TreeView<User> treeView = new TreeView<User>(rootNode);
-        users.addListener(new ListChangeListener<User>() {
-            @Override
-            public void onChanged(Change<? extends User> change) {
-                rootNode.getChildren().clear();
-                if (change == null) return;
-                for (User u : change.getList()) {
-                    rootNode.getChildren().add(new TreeItem<>(u));
-                }
-            }
-        });
-        treeView.setShowRoot(false);
-        treeView.setCellFactory(new Callback<TreeView<User>, TreeCell<User>>() {
-            @Override
-            public TreeCell<User> call(TreeView<User> userTreeView) {
-                return new TreeCell<User>() {
-                    @Override
-                    public void updateItem(User item, boolean empty) {
-                        super.updateItem(item, empty);
-                        if (!empty) {
-                            setText(item.getUserName());
-                            setGraphic(getTreeItem().getGraphic());
-                        }
-                    }
-                };
-            }
-        });
-        AnchorPane.setRightAnchor(heading, 40.0);
-        AnchorPane.setTopAnchor(heading, 15.0);
-
-
-        AnchorPane.setTopAnchor(treeView, 50.0);
-        AnchorPane.setRightAnchor(treeView, 25.0);
-        AnchorPane.setLeftAnchor(treeView, 25.0);
-
-        anchor.getChildren().addAll(heading, treeView);
-
-        GridPane.setHgrow(anchor, Priority.ALWAYS);
-        GridPane.setVgrow(anchor, Priority.ALWAYS);
-
-        return anchor;
-    }
-
-}

File JacpFXWebsocketChatClient/src/main/java/org/jacp/twitter/decoders/MessageDecoder.java

-/*
- * Copyright (c) 2013, Andy Moncsek, inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided
- * that the following conditions are met:
- *
- *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
- *    the following disclaimer in the documentation and/or other materials provided with the distribution.
- *
- *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
- *    promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING