[virtualcommons-svn] SF.net SVN: virtualcommons:[516] foraging/trunk
Status: Beta
Brought to you by:
alllee
From: <al...@us...> - 2010-05-10 23:32:00
|
Revision: 516 http://virtualcommons.svn.sourceforge.net/virtualcommons/?rev=516&view=rev Author: alllee Date: 2010-05-10 23:31:53 +0000 (Mon, 10 May 2010) Log Message: ----------- first cut at censored chat requests being displayed and approved/denied by the facilitator. Functional but needs some usability improvements like auto-scrolling when new chats come in (or dealing with approved chats by moving them to a different panel). Modified Paths: -------------- foraging/trunk/build.xml foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ChatPanel.java foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java foraging/trunk/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java foraging/trunk/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java Added Paths: ----------- foraging/trunk/src/main/java/edu/asu/commons/foraging/event/CensoredChatRequest.java foraging/trunk/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java foraging/trunk/src/main/resources/images/checked.gif foraging/trunk/src/main/resources/images/unchecked.gif Modified: foraging/trunk/build.xml =================================================================== --- foraging/trunk/build.xml 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/build.xml 2010-05-10 23:31:53 UTC (rev 516) @@ -234,6 +234,7 @@ optimize="off" deprecation="on" source="1.6" + includeAntRuntime="false" > <compilerarg value='-Xlint:unchecked'/> <classpath refid="project.classpath" /> Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ChatPanel.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ChatPanel.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ChatPanel.java 2010-05-10 23:31:53 UTC (rev 516) @@ -33,6 +33,8 @@ import edu.asu.commons.event.ChatEvent; import edu.asu.commons.event.ChatRequest; import edu.asu.commons.event.EventTypeProcessor; +import edu.asu.commons.foraging.conf.RoundConfiguration; +import edu.asu.commons.foraging.event.CensoredChatRequest; import edu.asu.commons.net.Identifier; @@ -117,10 +119,17 @@ if (message == null || "".equals(message) || targetIdentifier == null) { return; } - client.transmit(new ChatRequest(clientId, message, targetIdentifier)); - displayMessage(getChatHandle(clientId) -// + " -> " + getChatHandle(targetIdentifier) - , message); + RoundConfiguration roundConfiguration = client.getCurrentRoundConfiguration(); + if (roundConfiguration.isCensoredChat()) { + // FIXME: perform extra checks to see if we are able to send this message + client.transmit(new CensoredChatRequest(clientId, message, targetIdentifier)); + } + else { + client.transmit(new ChatRequest(clientId, message, targetIdentifier)); +// displayMessage(getChatHandle(clientId) +//// + " -> " + getChatHandle(targetIdentifier) +// , message); + } chatField.requestFocusInWindow(); chatField.setText(""); } @@ -254,7 +263,7 @@ chatInstructionsPane.setEditable(false); chatInstructionsPane.setBackground(Color.WHITE); JScrollPane chatInstructionsScrollPane = new JScrollPane(chatInstructionsPane); - chatInstructionsPane.setText(client.getDataModel().getRoundConfiguration().getChatInstructions()); + chatInstructionsPane.setText(client.getCurrentRoundConfiguration().getChatInstructions()); add(chatInstructionsScrollPane, BorderLayout.NORTH); add(messageScrollPane, BorderLayout.CENTER); Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java 2010-05-10 23:31:53 UTC (rev 516) @@ -280,8 +280,6 @@ /** * Utility class for throttling client-side messages. * - * @author <a href='All...@as...'>Allen Lee</a> - * @version $Revision$ */ private class MessageQueue implements Runnable { private final static int DEFAULT_MESSAGES_PER_SECOND = 8; @@ -418,6 +416,10 @@ return dataModel; } + public RoundConfiguration getCurrentRoundConfiguration() { + return dataModel.getRoundConfiguration(); + } + public static void main(String[] args) { Runnable createGuiRunnable = new Runnable() { public void run() { Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java 2010-05-10 23:31:53 UTC (rev 516) @@ -18,9 +18,11 @@ * * Something like: * - * Parameter name, value, type, instructions + * Parameter name, value, type, instructions * + * need to deal with i18n at some point as well.. * + * * * @author <a href='mailto:All...@as...'>Allen Lee</a> * @version $Rev$ @@ -62,8 +64,6 @@ private final static Map<String, ExperimentType> experimentTypeMap = new HashMap<String, ExperimentType>(3); - - public enum ExperimentType { TWO_DIMENSIONAL("2d"), ABSTRACT("abstract"), FORESTRY("forestry"); private final String name; @@ -507,6 +507,23 @@ return isTokensFieldOfVisionEnabled() || isSubjectsFieldOfVisionEnabled(); } + public boolean isCensoredChat() { + return getBooleanProperty("censored-chat-enabled", false); + } + + public String getCensoredChatInstructions() { + return getProperty("censored-chat-instructions", + "Your messages must be approved by our censor before they will be relayed to the rest of your group."); + } + + public int getNumberOfChatsPerSecond() { + return getIntProperty("chats-per-second", 5); + } + + public int getDelayBetweenChats() { + return getIntProperty("delay-between-chats", 0); + } + public StringBuilder getCurrentRoundInstructions() { return buildInstructions(new StringBuilder()); } @@ -518,16 +535,20 @@ instructionsBuilder.append(getInstructions()); if (isFieldOfVisionEnabled()) { // create note type box, test to see how - // JEditorPaneS render CSS / fieldsets. + // JEditorPaneS render CSS divs or fieldsets..? instructionsBuilder.append("<hr>"); instructionsBuilder.append(getFieldOfVisionInstructions()); } - + if (isChatEnabled()) { + instructionsBuilder.append("<hr>"); + instructionsBuilder.append("Before the beginning of this round you will be able to chat with the other members of your group for ").append(getChatDuration()).append(" seconds."); + } // and add the quiz instructions if the quiz is enabled. if (isQuizEnabled()) { instructionsBuilder.append("<hr>"); instructionsBuilder.append(getQuizInstructions()); } + return instructionsBuilder; } Added: foraging/trunk/src/main/java/edu/asu/commons/foraging/event/CensoredChatRequest.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/event/CensoredChatRequest.java (rev 0) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/event/CensoredChatRequest.java 2010-05-10 23:31:53 UTC (rev 516) @@ -0,0 +1,43 @@ +package edu.asu.commons.foraging.event; + +import edu.asu.commons.event.AbstractPersistableEvent; +import edu.asu.commons.event.ChatRequest; +import edu.asu.commons.event.ClientRequest; +import edu.asu.commons.net.Identifier; + +/** + * $Id$ + * + * Client chat request that should be forwarded on to the facilitator for approval. + * + * @author <a href='mailto:All...@as...'>Allen Lee</a> + * @version $Rev$ + */ +public class CensoredChatRequest extends AbstractPersistableEvent implements ClientRequest { + + private static final long serialVersionUID = -120847705184240264L; + + private Identifier target; + + public CensoredChatRequest(Identifier source, String message) { + this(source, message, Identifier.ALL); + } + + public CensoredChatRequest(Identifier source, String message, Identifier target) { + super(source, message); + this.target = target; + } + + public Identifier getTarget() { + return target; + } + + public ChatRequest toApprovedChatRequest() { + return new ChatRequest(getId(), getMessage(), getTarget()); + } + + public ChatRequest toDeniedChatRequest() { + return new ChatRequest(getId(), String.format("Your message: [%s] was not approved.", getMessage()), getId()); + } + +} Added: foraging/trunk/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java (rev 0) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java 2010-05-10 23:31:53 UTC (rev 516) @@ -0,0 +1,39 @@ +package edu.asu.commons.foraging.event; + +import edu.asu.commons.event.AbstractPersistableEvent; +import edu.asu.commons.event.ClientRequest; +import edu.asu.commons.net.Identifier; + +/** + * $Id$ + * + * Event used to forward censored chat requests to the facilitator. + * + * @author <a href='mailto:All...@as...'>Allen Lee</a> + * @version $Rev$ + */ +public class FacilitatorCensoredChatRequest extends AbstractPersistableEvent implements ClientRequest { + + private static final long serialVersionUID = -120847705184240264L; + + private CensoredChatRequest censoredChatRequest; + + public FacilitatorCensoredChatRequest(Identifier facilitatorId, CensoredChatRequest request) { + super(facilitatorId); + this.censoredChatRequest = request; + } + + public CensoredChatRequest getCensoredChatRequest() { + return censoredChatRequest; + } + + public Identifier getSource() { + return censoredChatRequest.getId(); + } + + public Identifier getTarget() { + return censoredChatRequest.getTarget(); + } + + +} Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java 2010-05-10 23:31:53 UTC (rev 516) @@ -16,6 +16,7 @@ import edu.asu.commons.foraging.conf.RoundConfiguration; import edu.asu.commons.foraging.conf.ServerConfiguration; import edu.asu.commons.foraging.event.BeginChatRoundRequest; +import edu.asu.commons.foraging.event.FacilitatorCensoredChatRequest; import edu.asu.commons.foraging.event.FacilitatorEndRoundEvent; import edu.asu.commons.foraging.event.FacilitatorSanctionUpdateEvent; import edu.asu.commons.foraging.event.FacilitatorUpdateEvent; @@ -82,6 +83,7 @@ facilitatorWindow.quizCompleted(); } }); + } public static Facilitator getInstance() { @@ -208,7 +210,7 @@ public static void main(String[] args) { Runnable createGuiRunnable = new Runnable() { public void run() { - Dimension dimension = new Dimension(700, 300); + Dimension dimension = new Dimension(700, 700); Facilitator facilitator = Facilitator.getInstance(); facilitator.connect(); JFrame frame = new JFrame(); Added: foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java (rev 0) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java 2010-05-10 23:31:53 UTC (rev 516) @@ -0,0 +1,184 @@ +package edu.asu.commons.foraging.facilitator; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.GroupLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.GroupLayout.Alignment; + +import edu.asu.commons.event.EventTypeProcessor; +import edu.asu.commons.foraging.event.CensoredChatRequest; +import edu.asu.commons.foraging.event.FacilitatorCensoredChatRequest; +import edu.asu.commons.util.ResourceLoader; + +/** + * $Id$ + * + * A JPanel component for approving chat messages. + * + * + * @author <a href='mailto:All...@as...'>Allen Lee</a> + * @version $Rev$ + */ +public class FacilitatorChatPanel { + + private Facilitator facilitator; + + private JPanel chatRequestsPanel; + private JScrollPane chatRequestsScrollPane; + + private GroupLayout groupLayout; + private GroupLayout.ParallelGroup chatTextParallelGroup; + private GroupLayout.ParallelGroup approveParallelGroup; + private GroupLayout.ParallelGroup statusLabelParallelGroup; + private GroupLayout.ParallelGroup denyParallelGroup; + + private GroupLayout.SequentialGroup verticalGroup; + + public FacilitatorChatPanel(Facilitator facilitator) { + this.facilitator = facilitator; + initGuiComponents(); + facilitator.addEventProcessor(new EventTypeProcessor<FacilitatorCensoredChatRequest>(FacilitatorCensoredChatRequest.class) { + public void handle(final FacilitatorCensoredChatRequest request) { + // add formatted message + approve / deny button to component + handleCensoredChatRequest(request); + } + }); + } + + private void handleCensoredChatRequest(final FacilitatorCensoredChatRequest request) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + CensoredChatRequestView censoredChatRequestView = new CensoredChatRequestView(request.getCensoredChatRequest()); + censoredChatRequestView.addToGroupLayout(); + chatRequestsScrollPane.scrollRectToVisible(chatRequestsPanel.getBounds()); + chatRequestsPanel.revalidate(); + } + }); + + + + } + + private void initGuiComponents() { + JPanel scrollablePanel = new JPanel(new BorderLayout()); + scrollablePanel.add(new JLabel("Chat requests"), BorderLayout.NORTH); + chatRequestsPanel = new JPanel(); + groupLayout = new GroupLayout(chatRequestsPanel); + chatRequestsPanel.setLayout(groupLayout); + groupLayout.setAutoCreateGaps(true); + GroupLayout.SequentialGroup horizontalGroup = groupLayout.createSequentialGroup(); + JLabel messagesLabel = new JLabel("Messages"); + JLabel approveLabel = new JLabel("Approve"); + JLabel statusLabel = new JLabel("Status"); + JLabel denyLabel = new JLabel("Deny"); + chatTextParallelGroup = groupLayout.createParallelGroup().addComponent(messagesLabel); + approveParallelGroup = groupLayout.createParallelGroup().addComponent(approveLabel); + statusLabelParallelGroup = groupLayout.createParallelGroup().addComponent(statusLabel); + denyParallelGroup = groupLayout.createParallelGroup().addComponent(denyLabel); + horizontalGroup.addGroup(chatTextParallelGroup).addGroup(approveParallelGroup).addGroup(statusLabelParallelGroup).addGroup(denyParallelGroup); + groupLayout.setHorizontalGroup(horizontalGroup); + + + verticalGroup = groupLayout.createSequentialGroup(); + GroupLayout.ParallelGroup rowParallelGroup = groupLayout.createParallelGroup(Alignment.BASELINE); + rowParallelGroup.addComponent(messagesLabel).addComponent(approveLabel).addComponent(statusLabel).addComponent(denyLabel); + verticalGroup.addGroup(rowParallelGroup); + groupLayout.setVerticalGroup(verticalGroup); + + + + scrollablePanel.add(chatRequestsPanel, BorderLayout.CENTER); + chatRequestsScrollPane = new JScrollPane(scrollablePanel); + chatRequestsScrollPane.setPreferredSize(new Dimension(300, 300)); + } + + public Component getComponent() { + return chatRequestsScrollPane; + } + + /** + * + * Mini component for a chat request that can be approved or denied. + * + */ + public class CensoredChatRequestView { + + private static final long serialVersionUID = -5819416143717776775L; + + private JButton approveButton; + private JButton denyButton; + private JLabel statusLabel; + + private JTextArea chatMessageTextArea; + + public JTextArea getChatMessageTextArea() { + return chatMessageTextArea; + } + + + public CensoredChatRequestView(final CensoredChatRequest request) { + chatMessageTextArea = createTextArea(request); + + approveButton = new JButton(); + denyButton = new JButton(); + approveButton.setIcon(new ImageIcon(ResourceLoader.getResourceAsUrl("images/checked.gif"))); + denyButton.setIcon(new ImageIcon(ResourceLoader.getResourceAsUrl("images/unchecked.gif"))); + statusLabel = new JLabel("Pending"); + + approveButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + facilitator.transmit(request.toApprovedChatRequest()); + updateChatStatus(" approved "); + + } + }); + denyButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + facilitator.transmit(request.toDeniedChatRequest()); + updateChatStatus(" denied "); + } + }); + } + + private void addToGroupLayout() { + chatTextParallelGroup.addComponent(chatMessageTextArea); + approveParallelGroup.addComponent(approveButton); + statusLabelParallelGroup.addComponent(statusLabel); + denyParallelGroup.addComponent(denyButton); + + GroupLayout.ParallelGroup rowParallelGroup = groupLayout.createParallelGroup(Alignment.BASELINE); + rowParallelGroup.addComponent(chatMessageTextArea).addComponent(approveButton).addComponent(statusLabel).addComponent(denyButton); + verticalGroup.addGroup(rowParallelGroup); + } + + private void updateChatStatus(String message) { + approveButton.setEnabled(false); + denyButton.setEnabled(false); + statusLabel.setText(message); + } + + private JTextArea createTextArea(CensoredChatRequest request) { + JTextArea textArea = new JTextArea( toString( request ) ); + textArea.setEditable(false); + return textArea; + } + + private String toString(CensoredChatRequest request) { + return String.format("%s: %s", request.getId(), request.getMessage()); + } + + } + +} Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java 2010-05-10 23:31:53 UTC (rev 516) @@ -20,6 +20,7 @@ import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JSplitPane; import javax.swing.ScrollPaneConstants; import edu.asu.commons.foraging.conf.RoundConfiguration; @@ -36,6 +37,8 @@ private static final long serialVersionUID = -9067316316468488000L; private Facilitator facilitator; + + private FacilitatorChatPanel facilitatorChatPanel; // private JFrame frame; private Dimension windowDimension; @@ -56,17 +59,17 @@ private int viewSpacing = 50; - private JMenuItem startExperimentMenuItem = null; + private JMenuItem startExperimentMenuItem; - private JMenuItem stopExperimentMenuItem = null; + private JMenuItem stopExperimentMenuItem; - private JMenuItem showInstructionsMenuItem = null; + private JMenuItem showInstructionsMenuItem; - private JMenuItem startRoundMenuItem = null; + private JMenuItem startRoundMenuItem; - private JMenuItem stopRoundMenuItem = null; + private JMenuItem stopRoundMenuItem; - private JMenuItem loadExperimentMenuItem = null; + private JMenuItem loadExperimentMenuItem; private JMenuBar menuBar; @@ -225,7 +228,11 @@ "CSAN Facilitator Instructions"); informationEditorPane.setPreferredSize(new Dimension(400, 400)); informationEditorPane.setEditable(false); + + facilitatorChatPanel = new FacilitatorChatPanel(facilitator); + JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + informationScrollPane = new JScrollPane(informationEditorPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); @@ -235,11 +242,14 @@ informationPanel.add(messageLabel, BorderLayout.NORTH); informationPanel.add(informationScrollPane, BorderLayout.CENTER); - setInstructions(facilitator.getServerConfiguration() - .getFacilitatorInstructions()); + setInstructions(facilitator.getServerConfiguration().getFacilitatorInstructions()); viewPane = new JScrollPane(); - add(informationPanel, BorderLayout.CENTER); + + splitPane.add(informationPanel); + splitPane.add(facilitatorChatPanel.getComponent()); + add(splitPane, BorderLayout.CENTER); + splitPane.setDividerLocation(0.5d); } public void initViewPanel() { Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java 2010-05-04 00:31:50 UTC (rev 515) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java 2010-05-10 23:31:53 UTC (rev 516) @@ -31,6 +31,7 @@ import edu.asu.commons.foraging.conf.ServerConfiguration; import edu.asu.commons.foraging.event.AgentInfoRequest; import edu.asu.commons.foraging.event.BeginChatRoundRequest; +import edu.asu.commons.foraging.event.CensoredChatRequest; import edu.asu.commons.foraging.event.ClientMovementRequest; import edu.asu.commons.foraging.event.ClientPoseUpdate; import edu.asu.commons.foraging.event.ClientPositionUpdateEvent; @@ -39,6 +40,7 @@ import edu.asu.commons.foraging.event.EnforcementMechanismUpdateEvent; import edu.asu.commons.foraging.event.EnforcementRankingRequest; import edu.asu.commons.foraging.event.ExplicitCollectionModeRequest; +import edu.asu.commons.foraging.event.FacilitatorCensoredChatRequest; import edu.asu.commons.foraging.event.FacilitatorEndRoundEvent; import edu.asu.commons.foraging.event.FacilitatorSanctionUpdateEvent; import edu.asu.commons.foraging.event.FacilitatorUpdateEvent; @@ -283,6 +285,12 @@ } } }); + addEventProcessor(new EventTypeProcessor<CensoredChatRequest>(CensoredChatRequest.class) { + public void handle(final CensoredChatRequest request) { + // send to facilitator immediately for approval + transmit(new FacilitatorCensoredChatRequest(facilitatorId, request)); + } + }); addEventProcessor(new EventTypeProcessor<ChatRequest>(ChatRequest.class) { public void handle(final ChatRequest request) { new Thread () { public void run() { relayChatRequest(request); } }.start(); @@ -760,11 +768,6 @@ ClientData clientData = clients.get(source); getLogger().info(String.format("chat from %s: [ %s ]", clientData.toString(), request)); for (Identifier targetId : clientData.getGroupDataModel().getClientIdentifiers()) { - if (targetId.equals(source)) { - // don't send a chat event back to the originator of the chat - // request - continue; - } ChatEvent chatEvent = new ChatEvent(targetId, request.toString(), source, true); transmit(chatEvent); } Added: foraging/trunk/src/main/resources/images/checked.gif =================================================================== (Binary files differ) Property changes on: foraging/trunk/src/main/resources/images/checked.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: foraging/trunk/src/main/resources/images/unchecked.gif =================================================================== (Binary files differ) Property changes on: foraging/trunk/src/main/resources/images/unchecked.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |