Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
Expand Down Expand Up @@ -596,7 +594,6 @@ abstract class BaseEditorActivity :
}

setupToolbar()
syncProjectToolbarRowForOrientation(resources.configuration.orientation)
setupDrawers()
content.tabs.addOnTabSelectedListener(this)

Expand Down Expand Up @@ -634,7 +631,6 @@ abstract class BaseEditorActivity :

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
syncProjectToolbarRowForOrientation(newConfig.orientation)
}

private fun setupToolbar() {
Expand Down Expand Up @@ -688,90 +684,6 @@ abstract class BaseEditorActivity :
}
}

private fun syncProjectToolbarRowForOrientation(currentOrientation: Int) {
val appBar = content.editorAppBarLayout
val titleToolbar = content.titleToolbar
val actionsToolbar = content.projectActionsToolbar

val titleParent = titleToolbar.parent as? ViewGroup ?: return
val actionsParent = actionsToolbar.parent as? ViewGroup ?: return
if (titleParent != actionsParent) return

val isLandscape = currentOrientation == Configuration.ORIENTATION_LANDSCAPE

if (isLandscape && titleParent === appBar) {
val insertAt =
minOf(
appBar.indexOfChild(titleToolbar),
appBar.indexOfChild(actionsToolbar),
).coerceAtLeast(0)
val row =
LinearLayout(this).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
layoutParams =
com.google.android.material.appbar.AppBarLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
}

appBar.removeView(titleToolbar)
appBar.removeView(actionsToolbar)

titleToolbar.layoutParams =
LinearLayout.LayoutParams(
0,
ViewGroup.LayoutParams.WRAP_CONTENT,
1f,
)
actionsToolbar.layoutParams =
LinearLayout
.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
).apply { marginEnd = SizeUtils.dp2px(8f) }

content.root.findViewById<TextView>(R.id.title_text)?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = SizeUtils.dp2px(8f)
}

row.addView(titleToolbar)
row.addView(actionsToolbar)
appBar.addView(row, insertAt)
return
}

if (!isLandscape && titleParent is LinearLayout && titleParent.parent === appBar) {
val row = titleParent
val insertAt = appBar.indexOfChild(row).coerceAtLeast(0)
row.removeView(titleToolbar)
row.removeView(actionsToolbar)
appBar.removeView(row)

titleToolbar.layoutParams =
com.google.android.material.appbar.AppBarLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
actionsToolbar.layoutParams =
com.google.android.material.appbar.AppBarLayout
.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
).apply {
topMargin = SizeUtils.dp2px(4f)
}

content.root.findViewById<TextView>(R.id.title_text)?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = SizeUtils.dp2px(16f)
}

appBar.addView(titleToolbar, insertAt)
appBar.addView(actionsToolbar, insertAt + 1)
}
}

private fun onSwipeRevealDragProgress(progress: Float) {
_binding?.apply {
contentCard.progress = progress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package com.itsaky.androidide.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.ConvertUtils
import com.google.android.material.shape.CornerFamily
Expand Down Expand Up @@ -81,39 +80,11 @@ class TemplateListAdapter(
}

root.setOnLongClickListener {
template.tooltipTag?.let { tag ->
template.tooltipTag?.let { _ ->
onLongClick?.invoke(template, it)
}
true // Consume the event
}
}
}

internal fun fillDiff(extras: Int) {
val count = itemCount
for (i in 1..extras) {
templates.add(Template.EMPTY)
}

val diff =
DiffUtil.calculateDiff(
object : DiffUtil.Callback() {
override fun getOldListSize(): Int = count

override fun getNewListSize(): Int = count + extras

override fun areItemsTheSame(
oldItemPosition: Int,
newItemPosition: Int,
): Boolean = newItemPosition < count && oldItemPosition == newItemPosition

override fun areContentsTheSame(
oldItemPosition: Int,
newItemPosition: Int,
): Boolean = areItemsTheSame(oldItemPosition, newItemPosition)
},
)

diff.dispatchUpdatesTo(this)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,19 @@ package com.itsaky.androidide.fragments

import android.os.Bundle
import android.view.View
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.content.res.Configuration
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import androidx.recyclerview.widget.GridLayoutManager
import com.itsaky.androidide.R
import com.itsaky.androidide.adapters.TemplateListAdapter
import com.itsaky.androidide.databinding.FragmentTemplateListBinding
import com.itsaky.androidide.idetooltips.TooltipManager
import com.itsaky.androidide.idetooltips.TooltipTag.EXIT_TO_MAIN
import com.itsaky.androidide.templates.ITemplateProvider
import com.itsaky.androidide.templates.ProjectTemplate
import com.itsaky.androidide.utils.FlexboxUtils
import com.itsaky.androidide.viewmodel.MainViewModel
import org.slf4j.LoggerFactory

Expand All @@ -49,9 +46,6 @@ class TemplateListFragment :
FragmentTemplateListBinding::bind,
) {
private var adapter: TemplateListAdapter? = null
private var layoutManager: FlexboxLayoutManager? = null

private lateinit var globalLayoutListener: OnGlobalLayoutListener

private val viewModel by viewModels<MainViewModel>(ownerProducer = { requireActivity() })

Expand All @@ -65,41 +59,27 @@ class TemplateListFragment :
) {
super.onViewCreated(view, savedInstanceState)

ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updatePadding(bottom = insets.bottom)
windowInsets
}

layoutManager = FlexboxLayoutManager(requireContext(), FlexDirection.ROW)
layoutManager!!.justifyContent = JustifyContent.SPACE_EVENLY

binding.list.layoutManager = layoutManager

// This makes sure that the items are evenly distributed in the list
// and the last row is always aligned to the start
globalLayoutListener =
FlexboxUtils.createGlobalLayoutListenerToDistributeFlexboxItemsEvenly(
{ adapter },
{ layoutManager },
) { adapter, diff ->
adapter.fillDiff(diff)
}
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updatePadding(bottom = insets.bottom)
windowInsets
}

binding.list.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
val gridLayoutManager = GridLayoutManager(requireContext(), 1)
binding.list.layoutManager = gridLayoutManager

binding.exitButton.setOnClickListener {
viewModel.setScreen(MainViewModel.SCREEN_MAIN)
}

binding.exitButton.setOnLongClickListener {
TooltipManager.showIdeCategoryTooltip(
context = requireContext(),
anchorView = binding.root,
tag = EXIT_TO_MAIN,
)
true
}
binding.exitButton.setOnLongClickListener {
TooltipManager.showIdeCategoryTooltip(
context = requireContext(),
anchorView = binding.root,
tag = EXIT_TO_MAIN,
)
true
}

viewModel.currentScreen.observe(viewLifecycleOwner) { current ->
if (current == MainViewModel.SCREEN_TEMPLATE_DETAILS) {
Expand All @@ -110,8 +90,27 @@ class TemplateListFragment :
}
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)

updateSpanCount()
}

private fun updateSpanCount() {
val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
val maxSpans = if (isLandscape) 6 else 4

val itemCount = binding.list.adapter?.itemCount ?: 0

val optimalSpans = maxOf(1, minOf(maxSpans, itemCount))

val layoutManager = binding.list.layoutManager as? GridLayoutManager
if (layoutManager != null && layoutManager.spanCount != optimalSpans) {
layoutManager.spanCount = optimalSpans
}
}

override fun onDestroyView() {
binding.list.viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener)
super.onDestroyView()
}

Expand All @@ -138,16 +137,15 @@ class TemplateListFragment :
},
onLongClick = { template, itemView ->
template.tooltipTag?.let { tag ->
TooltipManager.showIdeCategoryTooltip(
context = requireContext(),
anchorView = itemView,
tag = tag
)
}
},
TooltipManager.showIdeCategoryTooltip(
context = requireContext(),
anchorView = itemView,
tag = tag
)
}
},
)

binding.list.adapter = adapter
updateSpanCount()
}

}
68 changes: 38 additions & 30 deletions app/src/main/res/layout/content_editor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,40 +31,48 @@
android:fitsSystemWindows="false"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/title_toolbar"
<com.google.android.flexbox.FlexboxLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="0dp"
android:padding="0dp"
app:contentInsetStartWithNavigation="0dp"
app:contentInsetStart="0dp"
app:contentInsetEnd="0dp">

<TextView
android:id="@+id/title_text"
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="match_parent"
app:flexWrap="wrap"
app:alignItems="center">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/title_toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_flexGrow="1"
android:minHeight="0dp"
android:padding="0dp"
app:contentInsetStartWithNavigation="0dp"
app:contentInsetStart="0dp"
app:contentInsetEnd="0dp">

<TextView
android:id="@+id/title_text"
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:gravity="start|center_vertical"
android:maxLines="1"
android:ellipsize="end" />

</com.google.android.material.appbar.MaterialToolbar>

<com.itsaky.androidide.ui.ProjectActionsToolbar
android:id="@+id/project_actions_toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_flexShrink="0"
android:layout_marginTop="4dp"
android:layout_marginBottom="0dp"
android:minHeight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:gravity="start|center_vertical"
android:maxLines="1"
android:ellipsize="end" />

</com.google.android.material.appbar.MaterialToolbar>

<com.itsaky.androidide.ui.ProjectActionsToolbar
android:id="@+id/project_actions_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="0dp"
android:minHeight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp" />
android:paddingBottom="0dp" />
</com.google.android.flexbox.FlexboxLayout>

<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_indicator"
Expand Down
Loading