Improve the image editor.
A variety of improvements to the image editor, such as: - New, fullscreen styling - Smoother lines - Better text and sticker handling - Improved color picker with a history pallette - New highlighter toolpull/1/head
After Width: | Height: | Size: 961 B |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 788 B |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 561 B |
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 582 B |
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 139 B After Width: | Height: | Size: 708 B |
After Width: | Height: | Size: 654 B |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 506 B |
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 100 B After Width: | Height: | Size: 482 B |
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 984 B |
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 576 B |
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 685 B |
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 105 B After Width: | Height: | Size: 539 B |
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 429 B After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 990 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 675 B After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 134 B After Width: | Height: | Size: 763 B |
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 532 B After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 946 B |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 908 B After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 840 B |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<solid android:color="@color/white"/>
|
||||
</shape>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/circle_white"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/palette_item_foreground"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:src="@drawable/circle_white"
|
||||
android:layout_gravity="center"
|
||||
tools:tint="@color/red"/>
|
||||
|
||||
</FrameLayout>
|
@ -1,44 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context="org.thoughtcrime.securesms.scribbles.ScribbleActivity">
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/activity_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
tools:context="org.thoughtcrime.securesms.scribbles.ScribbleActivity">
|
||||
|
||||
<org.thoughtcrime.securesms.scribbles.ScribbleToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"/>
|
||||
<org.thoughtcrime.securesms.scribbles.widget.ScribbleView
|
||||
android:id="@+id/scribble_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center" />
|
||||
|
||||
<FrameLayout android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@color/grey_300"
|
||||
android:gravity="center">
|
||||
<org.thoughtcrime.securesms.scribbles.ScribbleHud
|
||||
android:id="@+id/scribble_hud"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<org.thoughtcrime.securesms.scribbles.widget.ScribbleView
|
||||
android:id="@+id/scribble_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"/>
|
||||
|
||||
<org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker
|
||||
android:id="@+id/scribble_color_picker"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="300dp"
|
||||
android:layout_gravity="top|right"
|
||||
android:layout_marginRight="25dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:pickerBorderWidth="1dp"
|
||||
app:pickerBorderColor="@color/grey_600"
|
||||
app:pickerColors="@array/scribble_colors"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_save_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|left"
|
||||
android:src="@drawable/ic_check_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="right|top"
|
||||
android:orientation="vertical"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_text_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_text_fields_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_draw_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_brush_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_highlight_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/baseline_highlight_white_24"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_sticker_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_tag_faces_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_undo_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_replay_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/scribble_delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_delete_white_24dp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||
|
||||
<org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker
|
||||
android:id="@+id/scribble_color_picker"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="170dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="12dp"
|
||||
app:pickerBorderWidth="4dp"
|
||||
app:pickerBorderColor="@color/white"
|
||||
app:pickerColors="@array/scribble_colors"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/scribble_color_palette"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</merge>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar">
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowTranslucentNavigation">true</item>
|
||||
</style>
|
||||
</resources>
|
@ -0,0 +1,250 @@
|
||||
package org.thoughtcrime.securesms.scribbles;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.scribbles.widget.ColorPaletteAdapter;
|
||||
import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The HUD (heads-up display) that contains all of the tools for interacting with
|
||||
* {@link org.thoughtcrime.securesms.scribbles.widget.ScribbleView}
|
||||
*/
|
||||
public class ScribbleHud extends FrameLayout {
|
||||
|
||||
private View drawButton;
|
||||
private View highlightButton;
|
||||
private View textButton;
|
||||
private View stickerButton;
|
||||
private View undoButton;
|
||||
private View deleteButton;
|
||||
private View saveButton;
|
||||
private VerticalSlideColorPicker colorPicker;
|
||||
private RecyclerView colorPalette;
|
||||
|
||||
private EventListener eventListener;
|
||||
private ColorPaletteAdapter colorPaletteAdapter;
|
||||
|
||||
public ScribbleHud(@NonNull Context context) {
|
||||
super(context);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public ScribbleHud(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public ScribbleHud(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
inflate(getContext(), R.layout.scribble_hud, this);
|
||||
|
||||
drawButton = findViewById(R.id.scribble_draw_button);
|
||||
highlightButton = findViewById(R.id.scribble_highlight_button);
|
||||
textButton = findViewById(R.id.scribble_text_button);
|
||||
stickerButton = findViewById(R.id.scribble_sticker_button);
|
||||
undoButton = findViewById(R.id.scribble_undo_button);
|
||||
deleteButton = findViewById(R.id.scribble_delete_button);
|
||||
saveButton = findViewById(R.id.scribble_save_button);
|
||||
colorPicker = findViewById(R.id.scribble_color_picker);
|
||||
colorPalette = findViewById(R.id.scribble_color_palette);
|
||||
|
||||
undoButton.setOnClickListener(v -> {
|
||||
if (eventListener != null) {
|
||||
eventListener.onUndo();
|
||||
}
|
||||
});
|
||||
|
||||
deleteButton.setOnClickListener(v -> {
|
||||
if (eventListener != null) {
|
||||
eventListener.onDelete();
|
||||
}
|
||||
setMode(Mode.NONE);
|
||||
});
|
||||
|
||||
saveButton.setOnClickListener(v -> {
|
||||
if (eventListener != null) {
|
||||
eventListener.onSave();
|
||||
}
|
||||
setMode(Mode.NONE);
|
||||
});
|
||||
|
||||
colorPaletteAdapter = new ColorPaletteAdapter();
|
||||
colorPaletteAdapter.setEventListener(colorPicker::setActiveColor);
|
||||
|
||||
colorPalette.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
colorPalette.setAdapter(colorPaletteAdapter);
|
||||
|
||||
setMode(Mode.NONE);
|
||||
}
|
||||
|
||||
public void setColorPalette(@NonNull Set<Integer> colors) {
|
||||
colorPaletteAdapter.setColors(colors);
|
||||
}
|
||||
|
||||
public void enterMode(@NonNull Mode mode) {
|
||||
setMode(mode, false);
|
||||
}
|
||||
|
||||
private void setMode(@NonNull Mode mode) {
|
||||
setMode(mode, true);
|
||||
}
|
||||
|
||||
private void setMode(@NonNull Mode mode, boolean notify) {
|
||||
switch (mode) {
|
||||
case NONE: presentModeNone(); break;
|
||||
case DRAW: presentModeDraw(); break;
|
||||
case HIGHLIGHT: presentModeHighlight(); break;
|
||||
case TEXT: presentModeText(); break;
|
||||
case STICKER: presentModeSticker(); break;
|
||||
}
|
||||
|
||||
if (notify && eventListener != null) {
|
||||
eventListener.onModeStarted(mode);
|
||||
}
|
||||
}
|
||||
|
||||
private void presentModeNone() {
|
||||
drawButton.setVisibility(VISIBLE);
|
||||
highlightButton.setVisibility(VISIBLE);
|
||||
textButton.setVisibility(VISIBLE);
|
||||
stickerButton.setVisibility(VISIBLE);
|
||||
|
||||
undoButton.setVisibility(GONE);
|
||||
deleteButton.setVisibility(GONE);
|
||||
colorPicker.setVisibility(GONE);
|
||||
colorPalette.setVisibility(GONE);
|
||||
|
||||
drawButton.setOnClickListener(v -> setMode(Mode.DRAW));
|
||||
highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT));
|
||||
textButton.setOnClickListener(v -> setMode(Mode.TEXT));
|
||||
stickerButton.setOnClickListener(v -> setMode(Mode.STICKER));
|
||||
}
|
||||
|
||||
private void presentModeDraw() {
|
||||
drawButton.setVisibility(VISIBLE);
|
||||
undoButton.setVisibility(VISIBLE);
|
||||
colorPicker.setVisibility(VISIBLE);
|
||||
colorPalette.setVisibility(VISIBLE);
|
||||
|
||||
highlightButton.setVisibility(GONE);
|
||||
textButton.setVisibility(GONE);
|
||||
stickerButton.setVisibility(GONE);
|
||||
deleteButton.setVisibility(GONE);
|
||||
|
||||
drawButton.setOnClickListener(v -> setMode(Mode.NONE));
|
||||
|
||||
colorPicker.setOnColorChangeListener(standardOnColorChangeListener);
|
||||
colorPicker.setActiveColor(Color.RED);
|
||||
}
|
||||
|
||||
private void presentModeHighlight() {
|
||||
highlightButton.setVisibility(VISIBLE);
|
||||
undoButton.setVisibility(VISIBLE);
|
||||
colorPicker.setVisibility(VISIBLE);
|
||||
colorPalette.setVisibility(VISIBLE);
|
||||
|
||||
drawButton.setVisibility(GONE);
|
||||
textButton.setVisibility(GONE);
|
||||
stickerButton.setVisibility(GONE);
|
||||
deleteButton.setVisibility(GONE);
|
||||
|
||||
highlightButton.setOnClickListener(v -> setMode(Mode.NONE));
|
||||
|
||||
colorPicker.setOnColorChangeListener(highlightOnColorChangeListener);
|
||||
colorPicker.setActiveColor(Color.YELLOW);
|
||||
}
|
||||
|
||||
private void presentModeText() {
|
||||
textButton.setVisibility(VISIBLE);
|
||||
deleteButton.setVisibility(VISIBLE);
|
||||
colorPicker.setVisibility(VISIBLE);
|
||||
colorPalette.setVisibility(VISIBLE);
|
||||
|
||||
drawButton.setVisibility(GONE);
|
||||
highlightButton.setVisibility(GONE);
|
||||
stickerButton.setVisibility(GONE);
|
||||
undoButton.setVisibility(GONE);
|
||||
|
||||
textButton.setOnClickListener(v -> setMode(Mode.NONE));
|
||||
|
||||
colorPicker.setOnColorChangeListener(standardOnColorChangeListener);
|
||||
colorPicker.setActiveColor(Color.WHITE);
|
||||
}
|
||||
|
||||
private void presentModeSticker() {
|
||||
stickerButton.setVisibility(VISIBLE);
|
||||
deleteButton.setVisibility(VISIBLE);
|
||||
|
||||
drawButton.setVisibility(GONE);
|
||||
highlightButton.setVisibility(GONE);
|
||||
textButton.setVisibility(GONE);
|
||||
undoButton.setVisibility(GONE);
|
||||
colorPicker.setVisibility(GONE);
|
||||
colorPalette.setVisibility(GONE);
|
||||
|
||||
stickerButton.setOnClickListener(v -> setMode(Mode.NONE));
|
||||
}
|
||||
|
||||
public int getActiveColor() {
|
||||
return colorPicker.getActiveColor();
|
||||
}
|
||||
|
||||
public void setActiveColor(int color) {
|
||||
colorPicker.setActiveColor(color);
|
||||
}
|
||||
|
||||
public void setEventListener(@Nullable EventListener eventListener) {
|
||||
this.eventListener = eventListener;
|
||||
}
|
||||
|
||||
private final VerticalSlideColorPicker.OnColorChangeListener standardOnColorChangeListener = new VerticalSlideColorPicker.OnColorChangeListener() {
|
||||
@Override
|
||||
public void onColorChange(int selectedColor) {
|
||||
if (eventListener != null) {
|
||||
eventListener.onColorChange(selectedColor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final VerticalSlideColorPicker.OnColorChangeListener highlightOnColorChangeListener = new VerticalSlideColorPicker.OnColorChangeListener() {
|
||||
@Override
|
||||
public void onColorChange(int selectedColor) {
|
||||
if (eventListener != null) {
|
||||
int r = Color.red(selectedColor);
|
||||
int g = Color.green(selectedColor);
|
||||
int b = Color.blue(selectedColor);
|
||||
int a = 128;
|
||||
|
||||
eventListener.onColorChange(Color.argb(a, r, g, b));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public enum Mode {
|
||||
NONE, DRAW, HIGHLIGHT, TEXT, STICKER
|
||||
}
|
||||
|
||||
public interface EventListener {
|
||||
void onModeStarted(@NonNull Mode mode);
|
||||
void onColorChange(int color);
|
||||
void onUndo();
|
||||
void onDelete();
|
||||
void onSave();
|
||||
}
|
||||
}
|
@ -1,240 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.scribbles;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class ScribbleToolbar extends Toolbar implements View.OnClickListener {
|
||||
|
||||
private enum Selected {
|
||||
NONE,
|
||||
STICKER,
|
||||
TEXT,
|
||||
BRUSH
|
||||
}
|
||||
|
||||
private int foregroundSelectedTint;
|
||||
private int foregroundUnselectedTint;
|
||||
|
||||
private LinearLayout toolsView;
|
||||
|
||||
private ImageView saveView;
|
||||
private ImageView brushView;
|
||||
private ImageView textView;
|
||||
private ImageView stickerView;
|
||||
|
||||
private ImageView separatorView;
|
||||
|
||||
private ImageView undoView;
|
||||
private ImageView deleteView;
|
||||
|
||||
private Drawable background;
|
||||
|
||||
@Nullable
|
||||
private ScribbleToolbarListener listener;
|
||||
|
||||
private int toolColor = Color.RED;
|
||||
private Selected selected = Selected.NONE;
|
||||
|
||||
public ScribbleToolbar(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ScribbleToolbar(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ScribbleToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
inflate(context, R.layout.scribble_toolbar, this);
|
||||
|
||||
this.toolsView = (LinearLayout) findViewById(R.id.tools_view);
|
||||
this.brushView = (ImageView) findViewById(R.id.brush_button);
|
||||
this.textView = (ImageView) findViewById(R.id.text_button);
|
||||
this.stickerView = (ImageView) findViewById(R.id.sticker_button);
|
||||
this.separatorView = (ImageView) findViewById(R.id.separator);
|
||||
this.saveView = (ImageView) findViewById(R.id.save);
|
||||
|
||||
this.undoView = (ImageView) findViewById(R.id.undo);
|
||||
this.deleteView = (ImageView) findViewById(R.id.delete);
|
||||
|
||||
this.background = getResources().getDrawable(R.drawable.circle_tintable);
|
||||
this.foregroundSelectedTint = getResources().getColor(R.color.white);
|
||||
this.foregroundUnselectedTint = getResources().getColor(R.color.grey_800);
|
||||
|
||||
this.undoView.setOnClickListener(this);
|
||||
this.brushView.setOnClickListener(this);
|
||||
this.textView.setOnClickListener(this);
|
||||
this.stickerView.setOnClickListener(this);
|
||||
this.separatorView.setOnClickListener(this);
|
||||
this.deleteView.setOnClickListener(this);
|
||||
this.saveView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setListener(@Nullable ScribbleToolbarListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setToolColor(int toolColor) {
|
||||
this.toolColor = toolColor;
|
||||
this.background.setColorFilter(new PorterDuffColorFilter(toolColor, PorterDuff.Mode.MULTIPLY));
|
||||
}
|
||||
|
||||
public int getToolColor() {
|
||||
return this.toolColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
this.toolsView.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
|
||||
|
||||
if (v == this.brushView) {
|
||||
boolean enabled = selected != Selected.BRUSH;
|
||||
setBrushSelected(enabled);
|
||||
if (listener != null) listener.onBrushSelected(enabled);
|
||||
} else if (v == this.stickerView) {
|
||||
setNoneSelected();
|
||||
if (listener != null) listener.onStickerSelected(true);
|
||||
} else if (v == this.textView) {
|
||||
boolean enabled = selected != Selected.TEXT;
|
||||
setTextSelected(enabled);
|
||||
if (listener != null) listener.onTextSelected(enabled);
|
||||
} else if (v == this.deleteView) {
|
||||
setNoneSelected();
|
||||
if (listener != null) listener.onDeleteSelected();
|
||||
} else if (v == this.undoView) {
|
||||
if (listener != null) listener.onPaintUndo();
|
||||
} else if (v == this.saveView) {
|
||||
if (listener != null) listener.onSave();
|
||||
}
|
||||
}
|
||||
|
||||
private void setBrushSelected(boolean enabled) {
|
||||
if (enabled) {
|
||||
|
||||
this.textView.setBackground(null);
|
||||
this.textView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.brushView.setBackground(background);
|
||||
this.brushView.setColorFilter(new PorterDuffColorFilter(foregroundSelectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.stickerView.setBackground(null);
|
||||
this.stickerView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.separatorView.setVisibility(View.VISIBLE);
|
||||
this.undoView.setVisibility(View.VISIBLE);
|
||||
this.deleteView.setVisibility(View.GONE);
|
||||
|
||||
this.selected = Selected.BRUSH;
|
||||
} else {
|
||||
this.brushView.setBackground(null);
|
||||
this.brushView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
this.separatorView.setVisibility(View.GONE);
|
||||
this.undoView.setVisibility(View.GONE);
|
||||
|
||||
this.selected = Selected.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextSelected(boolean enabled) {
|
||||
if (enabled) {
|
||||
this.brushView.setBackground(null);
|
||||
this.brushView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.textView.setBackground(background);
|
||||
this.textView.setColorFilter(new PorterDuffColorFilter(foregroundSelectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.stickerView.setBackground(null);
|
||||
this.stickerView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.separatorView.setVisibility(View.VISIBLE);
|
||||
this.undoView.setVisibility(View.GONE);
|
||||
this.deleteView.setVisibility(View.VISIBLE);
|
||||
|
||||
this.selected = Selected.TEXT;
|
||||
} else {
|
||||
this.textView.setBackground(null);
|
||||
this.textView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.separatorView.setVisibility(View.GONE);
|
||||
this.deleteView.setVisibility(View.GONE);
|
||||
|
||||
this.selected = Selected.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public void setStickerSelected(boolean enabled) {
|
||||
if (enabled) {
|
||||
this.brushView.setBackground(null);
|
||||
this.brushView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.textView.setBackground(null);
|
||||
this.textView.setColorFilter(new PorterDuffColorFilter(foregroundUnselectedTint, PorterDuff.Mode.MULTIPLY));
|
||||
|
||||
this.separatorView.setVisibility(View.VISIBLE);
|
||||
this.undoView.setVisibility(View.GONE);
|
||||
this.deleteView.setVisibility(View.VISIBLE);
|
||||
|
||||
this.selected = Selected.STICKER;
|
||||
} else {
|
||||
this.separatorView.setVisibility(View.GONE);
|
||||
this.deleteView.setVisibility(View.GONE);
|
||||
|
||||
this.selected = Selected.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNoneSelected() {
|
||||
setBrushSelected(false);
|
||||
setStickerSelected(false);
|
||||
setTextSelected(false);
|
||||
|
||||
this.selected = Selected.NONE;
|
||||
}
|
||||
|
||||
public interface ScribbleToolbarListener {
|
||||
public void onBrushSelected(boolean enabled);
|
||||
public void onPaintUndo();
|
||||
public void onTextSelected(boolean enabled);
|
||||
public void onStickerSelected(boolean enabled);
|
||||
public void onDeleteSelected();
|
||||
public void onSave();
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package org.thoughtcrime.securesms.scribbles.widget;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ColorPaletteAdapter extends RecyclerView.Adapter<ColorPaletteAdapter.ColorViewHolder> {
|
||||
|
||||
private final List<Integer> colors = new ArrayList<>();
|
||||
|
||||
private EventListener eventListener;
|
||||
|
||||
@Override
|
||||
public ColorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ColorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_color, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ColorViewHolder holder, int position) {
|
||||
holder.bind(colors.get(position), eventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return colors.size();
|
||||
}
|
||||
|
||||
public void setColors(@NonNull Collection<Integer> colors) {
|
||||
this.colors.clear();
|
||||
this.colors.addAll(colors);
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setEventListener(@Nullable EventListener eventListener) {
|
||||
this.eventListener = eventListener;
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public interface EventListener {
|
||||
void onColorSelected(int color);
|
||||
}
|
||||
|
||||
static class ColorViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView foreground;
|
||||
|
||||
ColorViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
foreground = itemView.findViewById(R.id.palette_item_foreground);
|
||||
}
|
||||
|
||||
void bind(int color, @Nullable EventListener eventListener) {
|
||||
foreground.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
if (eventListener != null) {
|
||||
itemView.setOnClickListener(v -> eventListener.onColorSelected(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|