зеркало из https://github.com/mozilla/gecko-dev.git
Bug 875750 - Provide a basic color picker for Android. r=mfinkle
This commit is contained in:
Родитель
8bc776ce98
Коммит
5ba16c0086
|
@ -166,7 +166,7 @@ pref("dom.experimental_forms", true);
|
|||
pref("dom.forms.number", true);
|
||||
// Don't enable <input type=color> yet as we don't have a color picker
|
||||
// implemented for Android (bug 875750)
|
||||
pref("dom.forms.color", false);
|
||||
pref("dom.forms.color", true);
|
||||
|
||||
/* extension manager and xpinstall */
|
||||
pref("xpinstall.whitelist.add", "addons.mozilla.org");
|
||||
|
|
|
@ -266,6 +266,7 @@ gbjar.sources += [
|
|||
'preferences/SyncPreference.java',
|
||||
'PrefsHelper.java',
|
||||
'PrivateTab.java',
|
||||
'prompts/ColorPickerInput.java',
|
||||
'prompts/IconGridInput.java',
|
||||
'prompts/Prompt.java',
|
||||
'prompts/PromptInput.java',
|
||||
|
@ -314,6 +315,7 @@ gbjar.sources += [
|
|||
'widget/AllCapsTextView.java',
|
||||
'widget/AnimatedHeightLayout.java',
|
||||
'widget/ArrowPopup.java',
|
||||
'widget/BasicColorPicker.java',
|
||||
'widget/ButtonToast.java',
|
||||
'widget/CheckableLinearLayout.java',
|
||||
'widget/ClickableWhenDisabledEditText.java',
|
||||
|
@ -430,6 +432,7 @@ ANDROID_RESFILES += [
|
|||
'resources/drawable-hdpi/bookmark_folder_closed.png',
|
||||
'resources/drawable-hdpi/bookmark_folder_opened.png',
|
||||
'resources/drawable-hdpi/close.png',
|
||||
'resources/drawable-hdpi/color_picker_row_bg.9.png',
|
||||
'resources/drawable-hdpi/copy.png',
|
||||
'resources/drawable-hdpi/cut.png',
|
||||
'resources/drawable-hdpi/favicon.png',
|
||||
|
@ -578,6 +581,7 @@ ANDROID_RESFILES += [
|
|||
'resources/drawable-mdpi/bookmarkdefaults_favicon_addons.png',
|
||||
'resources/drawable-mdpi/bookmarkdefaults_favicon_support.png',
|
||||
'resources/drawable-mdpi/close.png',
|
||||
'resources/drawable-mdpi/color_picker_row_bg.9.png',
|
||||
'resources/drawable-mdpi/copy.png',
|
||||
'resources/drawable-mdpi/cut.png',
|
||||
'resources/drawable-mdpi/desktop_notification.png',
|
||||
|
@ -718,6 +722,7 @@ ANDROID_RESFILES += [
|
|||
'resources/drawable-xhdpi/bookmark_folder_closed.png',
|
||||
'resources/drawable-xhdpi/bookmark_folder_opened.png',
|
||||
'resources/drawable-xhdpi/close.png',
|
||||
'resources/drawable-xhdpi/color_picker_row_bg.9.png',
|
||||
'resources/drawable-xhdpi/copy.png',
|
||||
'resources/drawable-xhdpi/cut.png',
|
||||
'resources/drawable-xhdpi/favicon.png',
|
||||
|
@ -818,6 +823,7 @@ ANDROID_RESFILES += [
|
|||
'resources/drawable/action_bar_button.xml',
|
||||
'resources/drawable/action_bar_button_inverse.xml',
|
||||
'resources/drawable/bookmark_folder.xml',
|
||||
'resources/drawable/color_picker_checkmark.xml',
|
||||
'resources/drawable/divider_horizontal.xml',
|
||||
'resources/drawable/divider_vertical.xml',
|
||||
'resources/drawable/handle_end_level.xml',
|
||||
|
@ -867,11 +873,13 @@ ANDROID_RESFILES += [
|
|||
'resources/layout/arrow_popup.xml',
|
||||
'resources/layout/autocomplete_list.xml',
|
||||
'resources/layout/autocomplete_list_item.xml',
|
||||
'resources/layout/basic_color_picker_dialog.xml',
|
||||
'resources/layout/bookmark_edit.xml',
|
||||
'resources/layout/bookmark_folder_row.xml',
|
||||
'resources/layout/bookmark_item_row.xml',
|
||||
'resources/layout/browser_search.xml',
|
||||
'resources/layout/browser_toolbar.xml',
|
||||
'resources/layout/color_picker_row.xml',
|
||||
'resources/layout/datetime_picker.xml',
|
||||
'resources/layout/doorhanger.xml',
|
||||
'resources/layout/doorhanger_button.xml',
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.widget.BasicColorPicker;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
|
||||
public class ColorPickerInput extends PromptInput {
|
||||
public static final String INPUT_TYPE = "color";
|
||||
public static final String LOGTAG = "GeckoColorPickerInput";
|
||||
|
||||
private boolean mShowAdvancedButton = true;
|
||||
private int mInitialColor;
|
||||
|
||||
public ColorPickerInput(JSONObject obj) {
|
||||
super(obj);
|
||||
String init = obj.optString("value");
|
||||
mInitialColor = Color.rgb(Integer.parseInt(init.substring(1,3), 16),
|
||||
Integer.parseInt(init.substring(3,5), 16),
|
||||
Integer.parseInt(init.substring(5,7), 16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(Context context) throws UnsupportedOperationException {
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
mView = inflater.inflate(R.layout.basic_color_picker_dialog, null);
|
||||
|
||||
BasicColorPicker cp = (BasicColorPicker) mView.findViewById(R.id.colorpicker);
|
||||
cp.setColor(mInitialColor);
|
||||
|
||||
return mView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
BasicColorPicker cp = (BasicColorPicker) mView.findViewById(R.id.colorpicker);
|
||||
int color = cp.getColor();
|
||||
return "#" + Integer.toHexString(color).substring(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyInputStyle() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.mozilla.gecko.util.GeckoEventResponder;
|
|||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.DateTimePicker;
|
||||
import org.mozilla.gecko.prompts.ColorPickerInput;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
|
||||
|
@ -108,8 +109,11 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
|||
}
|
||||
}
|
||||
|
||||
private View applyInputStyle(View view) {
|
||||
view.setPadding(mInputPaddingSize, 0, mInputPaddingSize, 0);
|
||||
private View applyInputStyle(View view, PromptInput input) {
|
||||
// Don't add padding to color picker views
|
||||
if (input.canApplyInputStyle()) {
|
||||
view.setPadding(mInputPaddingSize, 0, mInputPaddingSize, 0);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
|
@ -333,12 +337,14 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
|||
|
||||
if (length == 1) {
|
||||
root = mInputs[0].getView(mContext);
|
||||
applyInputStyle(root, mInputs[0]);
|
||||
scrollable |= mInputs[0].getScrollable();
|
||||
} else if (length > 1) {
|
||||
LinearLayout linearLayout = new LinearLayout(mContext);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int i = 0; i < length; i++) {
|
||||
View content = mInputs[i].getView(mContext);
|
||||
applyInputStyle(content, mInputs[i]);
|
||||
linearLayout.addView(content);
|
||||
scrollable |= mInputs[i].getScrollable();
|
||||
}
|
||||
|
@ -346,11 +352,11 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
|||
}
|
||||
|
||||
if (scrollable) {
|
||||
builder.setView(applyInputStyle(root));
|
||||
builder.setView(root);
|
||||
} else {
|
||||
ScrollView view = new ScrollView(mContext);
|
||||
view.addView(root);
|
||||
builder.setView(applyInputStyle(view));
|
||||
builder.setView(view);
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
Log.e(LOGTAG, "Error showing prompt inputs", ex);
|
||||
|
|
|
@ -350,6 +350,8 @@ public class PromptInput {
|
|||
return new LabelInput(obj);
|
||||
} else if (IconGridInput.INPUT_TYPE.equals(type)) {
|
||||
return new IconGridInput(obj);
|
||||
} else if (ColorPickerInput.INPUT_TYPE.equals(type)) {
|
||||
return new ColorPickerInput(obj);
|
||||
} else {
|
||||
for (String dtType : DateTimeInput.INPUT_TYPES) {
|
||||
if (dtType.equals(type)) {
|
||||
|
@ -375,4 +377,8 @@ public class PromptInput {
|
|||
public boolean getScrollable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canApplyInputStyle() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 218 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 212 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 224 B |
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="ring"
|
||||
android:innerRadius="15dip"
|
||||
android:thickness="4dip"
|
||||
android:useLevel="false">
|
||||
<solid android:color="@android:color/white"/>
|
||||
</shape>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.mozilla.gecko.widget.BasicColorPicker android:id="@+id/colorpicker"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:drawSelectorOnTop="true"
|
||||
android:choiceMode="singleChoice"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="0dip"
|
||||
android:listSelector="#22FFFFFF"
|
||||
android:layout_width="fill_parent"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Widget.TextView"
|
||||
style="@style/Widget.ListItem"
|
||||
android:background="@drawable/color_picker_row_bg"
|
||||
android:checkMark="@android:color/transparent"/>
|
|
@ -0,0 +1,139 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.widget;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.ListView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
|
||||
public class BasicColorPicker extends ListView {
|
||||
private final static String LOGTAG = "GeckoBasicColorPicker";
|
||||
private final static List<Integer> DEFAULT_COLORS = Arrays.asList(Color.rgb(215,57,32),
|
||||
Color.rgb(255,134,5),
|
||||
Color.rgb(255,203,19),
|
||||
Color.rgb(95,173,71),
|
||||
Color.rgb(84,201,168),
|
||||
Color.rgb(33,161,222),
|
||||
Color.rgb(16,36,87),
|
||||
Color.rgb(91,32,103),
|
||||
Color.rgb(212,221,228),
|
||||
Color.BLACK);
|
||||
|
||||
private static Drawable mCheckDrawable = null;
|
||||
private int mSelected = 0;
|
||||
final private ColorPickerListAdapter mAdapter;
|
||||
|
||||
public BasicColorPicker(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BasicColorPicker(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BasicColorPicker(Context context, AttributeSet attrs, int style) {
|
||||
this(context, attrs, style, DEFAULT_COLORS);
|
||||
}
|
||||
|
||||
public BasicColorPicker(Context context, AttributeSet attrs, int style, List<Integer> colors) {
|
||||
super(context, attrs, style);
|
||||
mAdapter = new ColorPickerListAdapter(context, new ArrayList<Integer>(colors));
|
||||
setAdapter(mAdapter);
|
||||
|
||||
setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
mSelected = position;
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mAdapter.getItem(mSelected);
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
if (!DEFAULT_COLORS.contains(color)) {
|
||||
mSelected = mAdapter.getCount();
|
||||
mAdapter.add(color);
|
||||
} else {
|
||||
mSelected = DEFAULT_COLORS.indexOf(color);
|
||||
}
|
||||
|
||||
setSelection(mSelected);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private Drawable getCheckDrawable() {
|
||||
if (mCheckDrawable == null) {
|
||||
Resources res = getContext().getResources();
|
||||
|
||||
TypedValue typedValue = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(android.R.attr.listPreferredItemHeight, typedValue, true);
|
||||
DisplayMetrics metrics = new android.util.DisplayMetrics();
|
||||
((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);
|
||||
int height = (int) typedValue.getDimension(metrics);
|
||||
|
||||
Drawable background = res.getDrawable(R.drawable.color_picker_row_bg);
|
||||
Rect r = new Rect();
|
||||
background.getPadding(r);
|
||||
height -= r.top + r.bottom;
|
||||
|
||||
mCheckDrawable = res.getDrawable(R.drawable.color_picker_checkmark);
|
||||
mCheckDrawable.setBounds(0, 0, height, height);
|
||||
}
|
||||
|
||||
return mCheckDrawable;
|
||||
}
|
||||
|
||||
private class ColorPickerListAdapter extends ArrayAdapter<Integer> {
|
||||
private final List<Integer> mColors;
|
||||
|
||||
public ColorPickerListAdapter(Context context, List<Integer> colors) {
|
||||
super(context, R.layout.color_picker_row, colors);
|
||||
mColors = colors;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View v = super.getView(position, convertView, parent);
|
||||
|
||||
Drawable d = v.getBackground();
|
||||
d.setColorFilter(getItem(position), PorterDuff.Mode.MULTIPLY);
|
||||
v.setBackground(d);
|
||||
|
||||
Drawable check = null;
|
||||
CheckedTextView checked = ((CheckedTextView) v);
|
||||
if (mSelected == position) {
|
||||
check = getCheckDrawable();
|
||||
}
|
||||
|
||||
checked.setCompoundDrawables(check, null, null, null);
|
||||
checked.setText("");
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Prompt.jsm");
|
||||
|
||||
function ColorPicker() {
|
||||
}
|
||||
|
||||
ColorPicker.prototype = {
|
||||
_initial: 0,
|
||||
_domWin: null,
|
||||
_title: "",
|
||||
|
||||
get strings() {
|
||||
delete this.strings;
|
||||
return this.strings = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
},
|
||||
|
||||
init: function(aParent, aTitle, aInitial) {
|
||||
this._domWin = aParent;
|
||||
this._initial = aInitial;
|
||||
this._title = aTitle;
|
||||
},
|
||||
|
||||
open: function(aCallback) {
|
||||
let p = new Prompt({ title: this._title,
|
||||
buttons: [
|
||||
this.strings.GetStringFromName("inputWidgetHelper.set"),
|
||||
this.strings.GetStringFromName("inputWidgetHelper.cancel")
|
||||
] })
|
||||
.addColorPicker({ value: this._initial })
|
||||
.show((data) => {
|
||||
if (data.button == 0)
|
||||
aCallback.done(data.color0);
|
||||
else
|
||||
aCallback.done(this._initial);
|
||||
});
|
||||
},
|
||||
|
||||
classID: Components.ID("{430b987f-bb9f-46a3-99a5-241749220b29}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIColorPicker])
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ColorPicker]);
|
|
@ -105,3 +105,7 @@ component {a78d7e59-b558-4321-a3d6-dffe2f1e76dd} Snippets.js
|
|||
contract @mozilla.org/snippets;1 {a78d7e59-b558-4321-a3d6-dffe2f1e76dd}
|
||||
category profile-after-change Snippets @mozilla.org/snippets;1
|
||||
category update-timer Snippets @mozilla.org/snippets;1,getService,snippets-update-timer,browser.snippets.updateInterval,86400
|
||||
|
||||
# ColorPicker.js
|
||||
component {430b987f-bb9f-46a3-99a5-241749220b29} ColorPicker.js
|
||||
contract @mozilla.org/colorpicker;1 {430b987f-bb9f-46a3-99a5-241749220b29}
|
||||
|
|
|
@ -13,6 +13,7 @@ XPIDL_MODULE = 'MobileComponents'
|
|||
EXTRA_COMPONENTS += [
|
||||
'AddonUpdateService.js',
|
||||
'BlocklistPrompt.js',
|
||||
'ColorPicker.js',
|
||||
'ContentDispatchChooser.js',
|
||||
'ContentPermissionPrompt.js',
|
||||
'DownloadManagerUI.js',
|
||||
|
|
|
@ -558,6 +558,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
|||
@BINPATH@/components/AddonUpdateService.js
|
||||
@BINPATH@/components/BlocklistPrompt.js
|
||||
@BINPATH@/components/BrowserCLH.js
|
||||
@BINPATH@/components/ColorPicker.js
|
||||
@BINPATH@/components/ContentDispatchChooser.js
|
||||
@BINPATH@/components/ContentPermissionPrompt.js
|
||||
@BINPATH@/components/DirectoryProvider.js
|
||||
|
|
|
@ -117,6 +117,14 @@ Prompt.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
addColorPicker: function(aOptions) {
|
||||
return this._addInput({
|
||||
type: "color",
|
||||
value: aOptions.value,
|
||||
id: aOptions.id
|
||||
});
|
||||
},
|
||||
|
||||
addLabel: function(aOptions) {
|
||||
return this._addInput({
|
||||
type: "label",
|
||||
|
|
|
@ -397,6 +397,10 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
|
|||
aResult = 1;
|
||||
break;
|
||||
|
||||
case eIntID_ColorPickerAvailable:
|
||||
aResult = 1;
|
||||
break;
|
||||
|
||||
case eIntID_WindowsDefaultTheme:
|
||||
case eIntID_WindowsThemeIdentifier:
|
||||
case eIntID_OperatingSystemVersionIdentifier:
|
||||
|
|
Загрузка…
Ссылка в новой задаче