Change list to recyclerview

This commit is contained in:
J-Jamet
2021-02-25 15:13:34 +01:00
parent 3a5df6a893
commit 80521f8ec2
22 changed files with 257 additions and 276 deletions

View File

@@ -242,7 +242,7 @@ class EntryActivity : LockingActivity() {
val entryInfo = entry.getEntryInfo(mDatabase) val entryInfo = entry.getEntryInfo(mDatabase)
// Assign title icon // Assign title icon
titleIconView?.assignDatabaseIcon(mDatabase!!.drawFactory, entryInfo.icon, iconColor) titleIconView?.assignDatabaseIcon(mDatabase!!.iconDrawableFactory, entryInfo.icon, iconColor)
// Assign title text // Assign title text
val entryTitle = entryInfo.title val entryTitle = entryInfo.title

View File

@@ -208,7 +208,7 @@ class EntryEditActivity : LockingActivity(),
.replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG) .replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
.commit() .commit()
entryEditFragment?.apply { entryEditFragment?.apply {
drawFactory = mDatabase?.drawFactory drawFactory = mDatabase?.iconDrawableFactory
setOnDateClickListener = { setOnDateClickListener = {
expiryTime.date.let { expiresDate -> expiryTime.date.let { expiresDate ->
val dateTime = DateTime(expiresDate) val dateTime = DateTime(expiresDate)

View File

@@ -535,8 +535,8 @@ class GroupActivity : LockingActivity(),
// Assign the group icon depending of IconPack or custom icon // Assign the group icon depending of IconPack or custom icon
iconView?.visibility = View.VISIBLE iconView?.visibility = View.VISIBLE
mCurrentGroup?.let { mCurrentGroup?.let {
if (mDatabase?.drawFactory != null) if (mDatabase?.iconDrawableFactory != null)
iconView?.assignDatabaseIcon(mDatabase?.drawFactory!!, it.icon, mIconColor) iconView?.assignDatabaseIcon(mDatabase?.iconDrawableFactory!!, it.icon, mIconColor)
if (toolbar != null) { if (toolbar != null) {
if (mCurrentGroup?.containsParent() == true) if (mCurrentGroup?.containsParent() == true)

View File

@@ -205,8 +205,8 @@ class GroupEditDialogFragment : DialogFragment(), IconPickerDialogFragment.IconP
} }
private fun assignIconView() { private fun assignIconView() {
if (mDatabase?.drawFactory != null) { if (mDatabase?.iconDrawableFactory != null) {
iconButtonView.assignDatabaseIcon(mDatabase?.drawFactory!!, mGroupInfo.icon, iconColor) iconButtonView.assignDatabaseIcon(mDatabase?.iconDrawableFactory!!, mGroupInfo.icon, iconColor)
} }
} }

View File

@@ -24,15 +24,13 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.* import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.fragments.IconCustomFragment import com.kunzisoft.keepass.adapters.IconPickerPagerAdapter
import com.kunzisoft.keepass.activities.fragments.IconStandardFragment
import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
class IconPickerDialogFragment : DialogFragment() { class IconPickerDialogFragment : DialogFragment() {
@@ -45,7 +43,12 @@ class IconPickerDialogFragment : DialogFragment() {
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
try { try {
iconPickerListener = context as IconPickerListener iconPickerListener = object : IconPickerListener {
override fun iconPicked(icon: IconImage) {
(context as IconPickerListener).iconPicked(icon)
dismiss()
}
}
} catch (e: ClassCastException) { } catch (e: ClassCastException) {
// The activity doesn't implement the interface, throw exception // The activity doesn't implement the interface, throw exception
throw ClassCastException(context.toString() throw ClassCastException(context.toString()
@@ -82,50 +85,14 @@ class IconPickerDialogFragment : DialogFragment() {
val root = layoutInflater.inflate(R.layout.fragment_icon_picker, container) val root = layoutInflater.inflate(R.layout.fragment_icon_picker, container)
viewPager = root.findViewById(R.id.icon_picker_pager) viewPager = root.findViewById(R.id.icon_picker_pager)
tabLayout = root.findViewById(R.id.icon_picker_tabs) tabLayout = root.findViewById(R.id.icon_picker_tabs)
iconPickerPagerAdapter = IconPickerPagerAdapter(childFragmentManager, { icon -> iconPickerPagerAdapter = IconPickerPagerAdapter(childFragmentManager)
iconPickerListener?.iconPicked(IconImage(icon)) iconPickerPagerAdapter.iconSelected = iconPickerListener
dismiss()
}, { icon ->
iconPickerListener?.iconPicked(IconImage(icon))
dismiss()
}
)
viewPager.adapter = iconPickerPagerAdapter viewPager.adapter = iconPickerPagerAdapter
tabLayout.setupWithViewPager(viewPager) tabLayout.setupWithViewPager(viewPager)
return root return root
} }
class IconPickerPagerAdapter(fragmentManager: FragmentManager,
iconStandardSelected: (icon: IconImageStandard) -> Unit,
iconCustomSelected: (icon: IconImageCustom) -> Unit)
: FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_SET_USER_VISIBLE_HINT) {
private val iconStandardFragment = IconStandardFragment()
private val iconCustomFragment = IconCustomFragment()
init {
iconStandardFragment.iconStandardPickerListener = iconStandardSelected
iconCustomFragment.iconCustomPickerListener = iconCustomSelected
}
override fun getCount(): Int = 2
override fun getItem(i: Int): Fragment {
return when (i) {
1 -> iconCustomFragment
else -> iconStandardFragment
}
}
override fun getPageTitle(position: Int): CharSequence {
return when (position) {
1 -> "Custom" //context.getString(R.string.iconStandard)
else -> "Standard" //context.getString(R.string.iconStandard)
}
}
}
interface IconPickerListener { interface IconPickerListener {
fun iconPicked(icon: IconImage) fun iconPicked(icon: IconImage)
} }

View File

@@ -1,98 +1,20 @@
package com.kunzisoft.keepass.activities.fragments package com.kunzisoft.keepass.activities.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.GridView
import android.widget.ImageView
import androidx.fragment.app.Fragment
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
import com.kunzisoft.keepass.database.element.icon.IconPool
import com.kunzisoft.keepass.icons.IconDrawableFactory
import com.kunzisoft.keepass.icons.assignDatabaseIcon
/** /**
* Content fragments * Content fragments
*/ */
class IconCustomFragment : Fragment() { class IconCustomFragment : IconFragment() {
private lateinit var currIconGridView: GridView override fun retrieveMainLayoutId(): Int {
private var iconPool: IconPool? = null return R.layout.fragment_icon_custom_picker
private var iconDrawableFactory: IconDrawableFactory? = null
var iconCustomPickerListener: ((icon: IconImageCustom) -> Unit)? = null
override fun onDetach() {
iconCustomPickerListener = null
super.onDetach()
} }
override fun onCreateView(inflater: LayoutInflater, override fun defineIconList(database: Database): List<IconImage> {
container: ViewGroup?, return database.iconPool.getCustomIconList()
savedInstanceState: Bundle?): View {
val root = inflater.inflate(R.layout.fragment_icon_standard_picker, container, false)
currIconGridView = root.findViewById(R.id.IconGridView)
return root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val database = Database.getInstance()
iconPool = database.iconPool
iconDrawableFactory = database.drawFactory
currIconGridView.adapter = IconCustomAdapter(requireActivity()).apply {
iconPool?.doForEachCustomIcon {
putIcon(it)
}
}
}
inner class IconCustomAdapter(private val context: Context) : BaseAdapter() {
private val customIconList = ArrayList<IconImageCustom>()
fun putIcon(icon: IconImageCustom) {
customIconList.add(icon)
}
override fun getCount(): Int {
return customIconList.size
}
override fun getItem(position: Int): Any {
return customIconList[position]
}
override fun getItemId(position: Int): Long {
return customIconList[position].uuid.leastSignificantBits
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val currentView: View = convertView
?: (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.inflate(R.layout.item_icon, parent, false)
val iconImage = IconImage(customIconList[position])
iconDrawableFactory?.let {
val iconImageView = currentView.findViewById<ImageView>(R.id.icon_image)
iconImageView.assignDatabaseIcon(it, iconImage)
}
currentView.setOnClickListener {
iconCustomPickerListener?.invoke(iconImage.custom)
}
return currentView
}
} }
} }

View File

@@ -0,0 +1,52 @@
package com.kunzisoft.keepass.activities.fragments
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
import com.kunzisoft.keepass.adapters.IconAdapter
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.icon.IconImage
abstract class IconFragment : Fragment() {
private lateinit var iconsGridView: RecyclerView
private lateinit var iconAdapter: IconAdapter
var iconListener: IconPickerDialogFragment.IconPickerListener? = null
abstract fun retrieveMainLayoutId(): Int
abstract fun defineIconList(database: Database): List<IconImage>
override fun onAttach(context: Context) {
super.onAttach(context)
val database = Database.getInstance()
iconAdapter = IconAdapter(requireActivity()).apply {
iconDrawableFactory = database.iconDrawableFactory
setList(defineIconList(database))
}
iconAdapter.iconPickerListener = iconListener
}
override fun onDetach() {
iconAdapter.iconPickerListener = null
super.onDetach()
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View {
val root = inflater.inflate(retrieveMainLayoutId(), container, false)
iconsGridView = root.findViewById(R.id.icons_grid_view)
iconsGridView.adapter = iconAdapter
return root
}
}

View File

@@ -1,89 +1,20 @@
package com.kunzisoft.keepass.activities.fragments package com.kunzisoft.keepass.activities.fragments
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.GridView
import android.widget.ImageView
import androidx.core.widget.ImageViewCompat
import androidx.fragment.app.Fragment
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.icon.IconImageStandard import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.icons.IconPack import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.icons.IconPackChooser
/** /**
* Content fragments * Content fragments
*/ */
class IconStandardFragment : Fragment() { class IconStandardFragment : IconFragment() {
private lateinit var currIconGridView: GridView override fun retrieveMainLayoutId(): Int {
private var iconPack: IconPack? = null return R.layout.fragment_icon_standard_picker
var iconStandardPickerListener: ((icon: IconImageStandard) -> Unit)? = null
override fun onDetach() {
iconStandardPickerListener = null
super.onDetach()
} }
override fun onCreateView(inflater: LayoutInflater, override fun defineIconList(database: Database): List<IconImage> {
container: ViewGroup?, return database.iconPool.getStandardIconList()
savedInstanceState: Bundle?): View {
val root = inflater.inflate(R.layout.fragment_icon_standard_picker, container, false)
currIconGridView = root.findViewById(R.id.IconGridView)
return root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
iconPack = IconPackChooser.getSelectedIconPack(requireContext())
currIconGridView.adapter = IconStandardAdapter(requireActivity())
}
inner class IconStandardAdapter(private val context: Context) : BaseAdapter() {
override fun getCount(): Int {
return iconPack?.numberOfIcons() ?: 0
}
override fun getItem(position: Int): Any? {
return null
}
override fun getItemId(position: Int): Long {
return 0
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val currentView: View = convertView
?: (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.inflate(R.layout.item_icon, parent, false)
iconPack?.let { iconPack ->
val iconImageView = currentView.findViewById<ImageView>(R.id.icon_image)
iconImageView.setImageResource(iconPack.iconToResId(position))
// Assign color if icons are tintable
if (iconPack.tintable()) {
// Retrieve the textColor to tint the icon
val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor))
ImageViewCompat.setImageTintList(iconImageView, ColorStateList.valueOf(ta.getColor(0, Color.BLACK)))
ta.recycle()
}
}
currentView.setOnClickListener {
iconStandardPickerListener?.invoke(IconImageStandard(position))
}
return currentView
}
} }
} }

View File

@@ -0,0 +1,59 @@
package com.kunzisoft.keepass.adapters
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.icons.IconDrawableFactory
import com.kunzisoft.keepass.icons.assignDatabaseIcon
class IconAdapter(context: Context) : RecyclerView.Adapter<IconAdapter.CustomIconViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private val iconList = ArrayList<IconImage>()
var iconDrawableFactory: IconDrawableFactory? = null
var iconPickerListener: IconPickerDialogFragment.IconPickerListener? = null
var tintColor : Int = Color.BLACK
init {
// Retrieve the textColor to tint the icon
val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor))
tintColor = ta.getColor(0, Color.BLACK)
ta.recycle()
}
fun setList(icon: List<IconImage>) {
iconList.clear()
iconList.addAll(icon)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomIconViewHolder {
val view = inflater.inflate(R.layout.item_icon, parent, false)
return CustomIconViewHolder(view)
}
override fun onBindViewHolder(holder: CustomIconViewHolder, position: Int) {
val icon = iconList[position]
iconDrawableFactory?.let {
holder.iconImageView.assignDatabaseIcon(it, icon, tintColor)
}
holder.itemView.setOnClickListener { iconPickerListener?.iconPicked(icon) }
}
override fun getItemCount(): Int {
return iconList.size
}
inner class CustomIconViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var iconImageView: ImageView = itemView.findViewById(R.id.icon_image)
}
}

View File

@@ -0,0 +1,34 @@
package com.kunzisoft.keepass.adapters
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
import com.kunzisoft.keepass.activities.fragments.IconCustomFragment
import com.kunzisoft.keepass.activities.fragments.IconStandardFragment
class IconPickerPagerAdapter(fragmentManager: FragmentManager)
: FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_SET_USER_VISIBLE_HINT) {
var iconSelected: IconPickerDialogFragment.IconPickerListener? = null
private val iconStandardFragment = IconStandardFragment()
private val iconCustomFragment = IconCustomFragment()
override fun getCount(): Int = 2
override fun getItem(i: Int): Fragment {
return when (i) {
1 -> iconCustomFragment
else -> iconStandardFragment
}.apply {
iconListener = iconSelected
}
}
override fun getPageTitle(position: Int): CharSequence {
return when (position) {
1 -> "Custom" //context.getString(R.string.iconStandard)
else -> "Standard" //context.getString(R.string.iconStandard)
}
}
}

View File

@@ -304,7 +304,7 @@ class NodeAdapter (private val context: Context)
} }
holder.imageIdentifier?.setColorFilter(iconColor) holder.imageIdentifier?.setColorFilter(iconColor)
holder.icon.apply { holder.icon.apply {
assignDatabaseIcon(mDatabase.drawFactory, subNode.icon, iconColor) assignDatabaseIcon(mDatabase.iconDrawableFactory, subNode.icon, iconColor)
// Relative size of the icon // Relative size of the icon
layoutParams?.apply { layoutParams?.apply {
height = (mIconDefaultDimension * mPrefSizeMultiplier).toInt() height = (mIconDefaultDimension * mPrefSizeMultiplier).toInt()

View File

@@ -82,7 +82,7 @@ class SearchEntryCursorAdapter(private val context: Context,
// Assign image // Assign image
viewHolder.imageViewIcon?.assignDatabaseIcon( viewHolder.imageViewIcon?.assignDatabaseIcon(
database.drawFactory, database.iconDrawableFactory,
currentEntry.icon, currentEntry.icon,
iconColor) iconColor)

View File

@@ -276,7 +276,7 @@ object AutofillHelper {
if (remoteViewsIcon != null) { if (remoteViewsIcon != null) {
presentation.assignDatabaseIcon(context, presentation.assignDatabaseIcon(context,
R.id.autofill_entry_icon, R.id.autofill_entry_icon,
Database.getInstance().drawFactory, Database.getInstance().iconDrawableFactory,
remoteViewsIcon, remoteViewsIcon,
ContextCompat.getColor(context, R.color.green)) ContextCompat.getColor(context, R.color.green))
} }
@@ -285,7 +285,7 @@ object AutofillHelper {
private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? { private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? {
return createIconFromDatabaseIcon(context, return createIconFromDatabaseIcon(context,
Database.getInstance().drawFactory, Database.getInstance().iconDrawableFactory,
entryInfo.icon, entryInfo.icon,
ContextCompat.getColor(context, R.color.green)) ContextCompat.getColor(context, R.color.green))
} }

View File

@@ -67,7 +67,7 @@ class Database {
var isReadOnly = false var isReadOnly = false
val drawFactory = IconDrawableFactory() val iconDrawableFactory = IconDrawableFactory()
var loaded = false var loaded = false
set(value) { set(value) {
@@ -625,7 +625,7 @@ class Database {
fun clear(filesDirectory: File? = null) { fun clear(filesDirectory: File? = null) {
iconPool.clearCache() iconPool.clearCache()
drawFactory.clearCache() iconDrawableFactory.clearCache()
// Delete the cache of the database if present // Delete the cache of the database if present
mDatabaseKDB?.clearCache() mDatabaseKDB?.clearCache()
mDatabaseKDBX?.clearCache() mDatabaseKDBX?.clearCache()

View File

@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.database.element.icon
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import com.kunzisoft.keepass.icons.IconPack.Companion.NB_ICONS
class IconImageStandard : Parcelable { class IconImageStandard : Parcelable {
@@ -31,7 +32,7 @@ class IconImageStandard : Parcelable {
} }
constructor(iconId: Int) { constructor(iconId: Int) {
if (iconId < MIN_ID || iconId > MAX_ID) if (iconId < 0 || iconId > NB_ICONS)
this.id = KEY_ID this.id = KEY_ID
else else
this.id = iconId this.id = iconId
@@ -72,8 +73,6 @@ class IconImageStandard : Parcelable {
const val KEY_ID = 0 const val KEY_ID = 0
const val TRASH_ID = 43 const val TRASH_ID = 43
const val FOLDER_ID = 48 const val FOLDER_ID = 48
const val MIN_ID = 0
const val MAX_ID = 48
@JvmField @JvmField
val CREATOR: Parcelable.Creator<IconImageStandard> = object : Parcelable.Creator<IconImageStandard> { val CREATOR: Parcelable.Creator<IconImageStandard> = object : Parcelable.Creator<IconImageStandard> {

View File

@@ -19,22 +19,31 @@
*/ */
package com.kunzisoft.keepass.database.element.icon package com.kunzisoft.keepass.database.element.icon
import com.kunzisoft.keepass.icons.IconPack.Companion.NB_ICONS
import java.util.ArrayList
import java.util.UUID import java.util.UUID
class IconPool { class IconPool {
private val standardCache = HashMap<Int, IconImageStandard?>() private val standardCache = List(NB_ICONS) {
IconImageStandard(it)
}
private val customCache = HashMap<UUID, IconImageCustom?>() private val customCache = HashMap<UUID, IconImageCustom?>()
fun getIcon(iconId: Int): IconImageStandard { fun getIcon(iconId: Int): IconImageStandard {
var icon: IconImageStandard? = standardCache[iconId] return standardCache[iconId]
}
if (icon == null) { fun getStandardIconList(): List<IconImage> {
icon = IconImageStandard(iconId) return standardCache.mapIndexed { _, iconImageStandard -> IconImage(iconImageStandard) }
standardCache[iconId] = icon }
}
return icon /*
* Custom
*/
fun putIcon(icon: IconImageCustom) {
customCache[icon.uuid] = icon
} }
fun getIcon(iconUuid: UUID): IconImageCustom { fun getIcon(iconUuid: UUID): IconImageCustom {
@@ -48,25 +57,22 @@ class IconPool {
return icon return icon
} }
fun putIcon(icon: IconImageCustom) {
customCache[icon.uuid] = icon
}
fun containsCustomIcons(): Boolean { fun containsCustomIcons(): Boolean {
return customCache.isNotEmpty() return customCache.isNotEmpty()
} }
fun doForEachCustomIcon(action: (customIcon: IconImageCustom) -> Unit) { fun getCustomIconList(): List<IconImage> {
val list = ArrayList<IconImage>(customCache.size)
for ((_, customIcon) in customCache) { for ((_, customIcon) in customCache) {
action.invoke(customIcon!!) list.add(IconImage(customIcon!!))
} }
return list
} }
/** /**
* Clear the cache of icons * Clear the cache of icons
*/ */
fun clearCache() { fun clearCache() {
standardCache.clear()
customCache.clear() customCache.clear()
} }
} }

View File

@@ -701,11 +701,11 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
xml.startTag(null, DatabaseKDBXXML.ElemCustomIcons) xml.startTag(null, DatabaseKDBXXML.ElemCustomIcons)
mDatabaseKDBX.iconPool.doForEachCustomIcon { customIcon -> mDatabaseKDBX.iconPool.getCustomIconList().forEach { icon ->
xml.startTag(null, DatabaseKDBXXML.ElemCustomIconItem) xml.startTag(null, DatabaseKDBXXML.ElemCustomIconItem)
writeUuid(DatabaseKDBXXML.ElemCustomIconItemID, customIcon.uuid) writeUuid(DatabaseKDBXXML.ElemCustomIconItemID, icon.custom.uuid)
writeObject(DatabaseKDBXXML.ElemCustomIconItemData, String(Base64.encode(customIcon.imageData, BASE_64_FLAG))) writeObject(DatabaseKDBXXML.ElemCustomIconItemData, String(Base64.encode(icon.custom.imageData, BASE_64_FLAG)))
xml.endTag(null, DatabaseKDBXXML.ElemCustomIconItem) xml.endTag(null, DatabaseKDBXXML.ElemCustomIconItem)
} }

View File

@@ -111,21 +111,16 @@ class IconDrawableFactory {
fun getIconSuperDrawable(context: Context, icon: IconImage, width: Int, tint: Boolean = false, tintColor: Int = Color.WHITE): SuperDrawable { fun getIconSuperDrawable(context: Context, icon: IconImage, width: Int, tint: Boolean = false, tintColor: Int = Color.WHITE): SuperDrawable {
return if (!icon.custom.isUnknown) { return if (!icon.custom.isUnknown) {
SuperDrawable(getIconDrawable(context.resources, icon.custom)) SuperDrawable(getIconDrawable(context.resources, icon.custom))
} else IconPackChooser.getSelectedIconPack(context)?.iconToResId(icon.standard.id)?.let { resId -> } else {
getIconSuperDrawable(context, resId, width, tint, tintColor) val iconPack = IconPackChooser.getSelectedIconPack(context)
} ?: run { iconPack?.iconToResId(icon.standard.id)?.let { iconId ->
SuperDrawable(PatternIcon(context.resources).blankDrawable) SuperDrawable(getIconDrawable(context.resources, iconId, width, tint, tintColor), iconPack.tintable())
} ?: run {
SuperDrawable(PatternIcon(context.resources).blankDrawable)
}
} }
} }
/**
* Get the [SuperDrawable] IconImageStandard from [iconId] (cache, or build it and add it to the cache if not exists yet)
* , then [tint] it with [tintColor] if needed
*/
fun getIconSuperDrawable(context: Context, iconId: Int, width: Int, tint: Boolean, tintColor: Int): SuperDrawable {
return SuperDrawable(getIconDrawable(context.resources, iconId, width, tint, tintColor), true)
}
/** /**
* Key class to retrieve a Drawable in the cache if it's tinted or not * Key class to retrieve a Drawable in the cache if it's tinted or not
*/ */
@@ -258,28 +253,6 @@ class IconDrawableFactory {
} }
/**
* Assign a default database icon to an ImageView and tint it with [tintColor] if needed
*/
fun ImageView.assignDefaultDatabaseIcon(iconFactory: IconDrawableFactory,
tintColor: Int = Color.WHITE) {
try {
IconPackChooser.getSelectedIconPack(context)?.let { selectedIconPack ->
iconFactory.assignDrawableToImageView(
iconFactory.getIconSuperDrawable(context,
selectedIconPack.defaultIconId,
width,
selectedIconPack.tintable(),
tintColor),
this,
selectedIconPack.tintable(),
tintColor)
}
} catch (e: Exception) {
Log.e(ImageView::class.java.name, "Unable to assign icon in image view", e)
}
}
/** /**
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed * Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
*/ */

View File

@@ -134,7 +134,6 @@ class IconPack(packageName: String, resources: Resources, resourceId: Int) {
} }
companion object { companion object {
const val NB_ICONS = 68
private const val NB_ICONS = 68
} }
} }

View File

@@ -93,7 +93,7 @@ object IconPackChooser {
fun setSelectedIconPack(iconPackIdString: String?) { fun setSelectedIconPack(iconPackIdString: String?) {
for (iconPack in iconPackList) { for (iconPack in iconPackList) {
if (iconPack.id == iconPackIdString) { if (iconPack.id == iconPackIdString) {
Database.getInstance().drawFactory.clearCache() Database.getInstance().iconDrawableFactory.clearCache()
iconPackSelected = iconPack iconPackSelected = iconPack
break break
} }

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 Jeremy Jamet / Kunzisoft.
This file is part of KeePassDX.
KeePassDX 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.
KeePassDX 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 KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/icons_grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
android:verticalSpacing="32dp"
android:paddingTop="20dp"
android:gravity="center"
android:layout_gravity="center"
android:columnWidth="64dp"
android:numColumns="auto_fit"
android:stretchMode="spacingWidthUniform">
</androidx.recyclerview.widget.RecyclerView>

View File

@@ -17,10 +17,14 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>. along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--> -->
<GridView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.RecyclerView
android:id="@+id/IconGridView" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/icons_grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
android:verticalSpacing="32dp" android:verticalSpacing="32dp"
android:paddingTop="20dp" android:paddingTop="20dp"
android:gravity="center" android:gravity="center"
@@ -28,4 +32,4 @@
android:columnWidth="64dp" android:columnWidth="64dp"
android:numColumns="auto_fit" android:numColumns="auto_fit"
android:stretchMode="spacingWidthUniform"> android:stretchMode="spacingWidthUniform">
</GridView> </androidx.recyclerview.widget.RecyclerView>