Add ComponentBuilder + make events final

An example of ComponentBuilder usage can be found at CommandAlertRaw
This commit is contained in:
Thinkofdeath 2013-12-10 11:50:34 +00:00
parent bc746a546f
commit 5d68b422e5
8 changed files with 199 additions and 40 deletions

View File

@ -81,6 +81,8 @@ public abstract class BaseComponent
setUnderlined( old.isUnderlined() ); setUnderlined( old.isUnderlined() );
setStrikethrough( old.isStrikethroughRaw() ); setStrikethrough( old.isStrikethroughRaw() );
setObfuscated( old.isObfuscatedRaw() ); setObfuscated( old.isObfuscatedRaw() );
setClickEvent( old.getClickEvent() );
setHoverEvent( old.getHoverEvent() );
} }
/** /**

View File

@ -7,41 +7,39 @@ import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@Getter @Getter
@Setter
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor final public class ClickEvent
public class ClickEvent
{ {
/** /**
* The type of action to preform on click * The type of action to preform on click
*/ */
private Action action; private final Action action;
/** /**
* Depends on action * Depends on action
* @see net.md_5.bungee.api.chat.ClickEvent.Action * @see net.md_5.bungee.api.chat.ClickEvent.Action
*/ */
private String value; private final String value;
public enum Action public enum Action
{ {
/** /**
* Open a url at the path given by * Open a url at the path given by
* {@link net.md_5.bungee.api.chat.ClickEvent#setValue(String)} * {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
*/ */
OPEN_URL, OPEN_URL,
/** /**
* Open a file at the path given by * Open a file at the path given by
* {@link net.md_5.bungee.api.chat.ClickEvent#setValue(String)} * {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
*/ */
OPEN_FILE, OPEN_FILE,
/** /**
* Run the command given by * Run the command given by
* {@link net.md_5.bungee.api.chat.ClickEvent#setValue(String)} * {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
*/ */
RUN_COMMAND, RUN_COMMAND,
/** /**
* Inserts the string given by * Inserts the string given by
* {@link net.md_5.bungee.api.chat.ClickEvent#setValue(String)} * {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
* into the players text box * into the players text box
*/ */
SUGGEST_COMMAND SUGGEST_COMMAND

View File

@ -0,0 +1,157 @@
package net.md_5.bungee.api.chat;
import lombok.NoArgsConstructor;
import net.md_5.bungee.api.ChatColor;
import java.util.ArrayList;
import java.util.List;
/**
* ComponentBuilder simplifies creating basic messages by allowing
* the use of a chainable builder.
* <p/>
* <pre>
* new ComponentBuilder("Hello ").color(ChatColor.RED).
* append("World").color(ChatColor.BLUE).
* append("!").bold(true).create();
* </pre>
* <p/>
* All methods (excluding {@link #append(String)} and {@link #create()}
* work on the last part appended to the builder, so in the example
* above "Hello " would be {@link net.md_5.bungee.api.ChatColor#RED}
* and "World" would be {@link net.md_5.bungee.api.ChatColor#BLUE} but
* "!" would be bold and {@link net.md_5.bungee.api.ChatColor#BLUE}
* because append copies the previous part's formatting
*/
public class ComponentBuilder
{
private TextComponent current;
private List<BaseComponent> parts = new ArrayList<>();
/**
* Creates a componentBuilder with the given text as the
* first part.
*
* @param text the first text element
*/
public ComponentBuilder(String text)
{
current = new TextComponent( text );
}
/**
* Appends the text to the builder and makes it the current
* target for formatting. The text will have all the
* formatting from the previous part.
*
* @param text the text to append
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder append(String text)
{
parts.add( current );
current = new TextComponent( current );
current.setText( text );
return this;
}
/**
* Sets the color of the current part.
*
* @param color the new color
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder color(ChatColor color)
{
current.setColor( color );
return this;
}
/**
* Sets whether the current part is bold.
*
* @param bold whether this part is bold
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder bold(boolean bold)
{
current.setBold( bold );
return this;
}
/**
* Sets whether the current part is italic
*
* @param italic whether this part is italic
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder italic(boolean italic)
{
current.setItalic( italic );
return this;
}
/**
* Sets whether the current part is underlined
*
* @param underlined whether this part is underlined
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder underlined(boolean underlined)
{
current.setUnderlined( underlined );
return this;
}
/**
* Sets whether the current part is strikethrough
*
* @param strikethrough whether this part is strikethrough
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder strikethrough(boolean strikethrough)
{
current.setStrikethrough( strikethrough );
return this;
}
/**
* Sets whether the current pat is obfuscated
*
* @param obfuscated whether this part is obfuscated
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder obfuscated(boolean obfuscated)
{
current.setObfuscated( obfuscated );
return this;
}
/**
* Sets the click event for the current part.
* @param clickEvent
* @return
*/
public ComponentBuilder event(ClickEvent clickEvent)
{
current.setClickEvent( clickEvent );
return this;
}
public ComponentBuilder event(HoverEvent hoverEvent)
{
current.setHoverEvent( hoverEvent );
return this;
}
/**
* Returns the components needed to display the message
* created by this builder
* @return the created components
*/
public BaseComponent[] create()
{
parts.add( current );
return parts.toArray( new BaseComponent[parts.size()] );
}
}

View File

@ -5,14 +5,12 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@NoArgsConstructor
@Getter @Getter
@Setter
@AllArgsConstructor @AllArgsConstructor
public class HoverEvent final public class HoverEvent
{ {
private Action action; private final Action action;
private BaseComponent value; private final BaseComponent[] value;
public enum Action public enum Action
{ {

View File

@ -94,19 +94,10 @@ public class TextComponent extends BaseComponent
TextComponent old = component; TextComponent old = component;
component = new TextComponent( old ); component = new TextComponent( old );
ClickEvent clickEvent = new ClickEvent();
clickEvent.setAction( ClickEvent.Action.OPEN_URL );
String urlString = message.substring( i, pos ); String urlString = message.substring( i, pos );
if ( urlString.startsWith( "http" ) )
{
component.setText( urlString ); component.setText( urlString );
clickEvent.setValue( urlString ); component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL,
} else urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) );
{
component.setText( urlString );
clickEvent.setValue( "http://" + urlString );
}
component.setClickEvent( clickEvent );
components.add( component ); components.add( component );
i += pos - i - 1; i += pos - i - 1;
component = old; component = old;

View File

@ -55,11 +55,13 @@ public class BaseComponentSerializer
if ( object.has( "hoverEvent" ) ) if ( object.has( "hoverEvent" ) )
{ {
JsonObject event = object.getAsJsonObject( "hoverEvent" ); JsonObject event = object.getAsJsonObject( "hoverEvent" );
HoverEvent hoverEvent = new HoverEvent(); BaseComponent[] res;
hoverEvent.setAction( HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase() ) ); if (event.get("value").isJsonArray()) {
BaseComponent res = context.deserialize( event.get( "value" ), BaseComponent.class ); res = context.deserialize( event.get( "value" ), BaseComponent[].class );
hoverEvent.setValue( res ); } else {
component.setHoverEvent( hoverEvent ); res = new BaseComponent[]{context.<BaseComponent>deserialize( event.get( "value" ), BaseComponent.class )};
}
component.setHoverEvent( new HoverEvent( HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase() ), res ) );
} }
} }

View File

@ -4,6 +4,7 @@ import com.google.common.base.Joiner;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Command;
@ -34,15 +35,12 @@ public class CommandAlertRaw extends Command
ProxyServer.getInstance().broadcast( ComponentSerializer.parse( message ) ); ProxyServer.getInstance().broadcast( ComponentSerializer.parse( message ) );
} catch ( Exception e ) } catch ( Exception e )
{ {
TextComponent error = new TextComponent( "An error occurred while parsing your message. (Hover for details)" ); sender.sendMessage(
error.setColor( ChatColor.RED ); new ComponentBuilder( "An error occured while parsing your message. (Hover for details)" ).
error.setUnderlined( true ); color( ChatColor.RED ).underlined( true ).
event( new HoverEvent( HoverEvent.Action.SHOW_TEXT,
TextComponent errorMessage = new TextComponent( e.getMessage() ); new ComponentBuilder( e.getMessage() ).color( ChatColor.RED ).create() ) ).
errorMessage.setColor( ChatColor.RED ); create() );
error.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, errorMessage ) );
sender.sendMessage( error );
} }
} }
} }

View File

@ -3,6 +3,7 @@ package net.md_5.bungee.chat;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent; import net.md_5.bungee.api.chat.TranslatableComponent;
import org.junit.Assert; import org.junit.Assert;
@ -66,4 +67,16 @@ public class ComponentsTest
Assert.assertEquals( ChatColor.WHITE + "Page " + ChatColor.WHITE + "5" + ChatColor.WHITE + " of " + ChatColor.WHITE + "50", positional.toLegacyText() ); Assert.assertEquals( ChatColor.WHITE + "Page " + ChatColor.WHITE + "5" + ChatColor.WHITE + " of " + ChatColor.WHITE + "50", positional.toLegacyText() );
} }
@Test
public void testBuilder()
{
BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).
append( "World" ).bold( true ).color( ChatColor.BLUE ).
append( "!" ).color( ChatColor.YELLOW ).create();
Assert.assertEquals( "Hello World!", BaseComponent.toPlainText( components ) );
Assert.assertEquals( ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD +
"World" + ChatColor.YELLOW + ChatColor.BOLD + "!", BaseComponent.toLegacyText( components ) );
}
} }