Skip to content

Commit

Permalink
First pass at implementing per-layout logic for keytip anchoring
Browse files Browse the repository at this point in the history
Implement custom anchoring for small, medium, big and tile presentation states, as well as a custom presentation state for the ribbon task toggle buttons that positions its keytips along the bottom edge.

For #56
  • Loading branch information
kirill-grouchnikov committed Sep 12, 2023
1 parent a5f1283 commit 36de6ae
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1557,14 +1557,14 @@ internal fun <M : BaseCommandMenuContentModel,
KeyTipTracker.trackKeyTipOffset(
originalProjection,
presentationModel.actionKeyTip!!,
layoutManager.getActionKeyTipAnchorCenterPoint(layoutInfo)
layoutManager.getActionKeyTipAnchorCenterPoint(command, presentationModel, layoutInfo)
)
}
if ((presentationModel.popupKeyTip != null) && !layoutInfo.popupClickArea.isEmpty) {
KeyTipTracker.trackKeyTipOffset(
originalProjection,
presentationModel.popupKeyTip!!,
layoutManager.getPopupKeyTipAnchorCenterPoint(layoutInfo)
layoutManager.getPopupKeyTipAnchorCenterPoint(command, presentationModel, layoutInfo)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,22 @@ interface CommandButtonLayoutManager : MeasureScope {
preLayoutInfo: CommandButtonPreLayoutInfo
): CommandButtonLayoutInfo

fun getActionKeyTipAnchorCenterPoint(layoutInfo: CommandButtonLayoutInfo): Offset {
open fun getActionKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutInfo
): Offset {
return Offset(
(layoutInfo.actionClickArea.left + layoutInfo.actionClickArea.right) / 2.0f,
(layoutInfo.actionClickArea.top + layoutInfo.actionClickArea.bottom) / 2.0f,
)
}

fun getPopupKeyTipAnchorCenterPoint(layoutInfo: CommandButtonLayoutInfo): Offset {
open fun getPopupKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutInfo
): Offset {
return Offset(
(layoutInfo.popupClickArea.left + layoutInfo.popupClickArea.right) / 2.0f,
(layoutInfo.popupClickArea.top + layoutInfo.popupClickArea.bottom) / 2.0f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.pushingpixels.aurora.component.layout

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.text.Paragraph
Expand Down Expand Up @@ -419,6 +420,30 @@ internal open class CommandButtonLayoutManagerBig(
popupActionRect = popupActionRect
)
}

override fun getActionKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
// horizontally centered at the bottom edge of the action click area
return Offset(
x = layoutInfo.actionClickArea.left + layoutInfo.actionClickArea.width / 2,
y = layoutInfo.actionClickArea.top + layoutInfo.actionClickArea.height
)
}

override fun getPopupKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
// horizontally centered at the bottom edge of the popup click area
return Offset(
x = layoutInfo.popupClickArea.left + layoutInfo.popupClickArea.width / 2,
y = layoutInfo.popupClickArea.top + layoutInfo.popupClickArea.height
)
}
}

internal class CommandButtonLayoutManagerBigFitToIcon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
*/
package org.pushingpixels.aurora.component.layout

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.text.Paragraph
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.*
import org.pushingpixels.aurora.common.AuroraInternalApi
import org.pushingpixels.aurora.component.model.*
import kotlin.math.max

internal open class CommandButtonLayoutManagerMedium(
@AuroraInternalApi
open class CommandButtonLayoutManagerMedium(
override val layoutDirection: LayoutDirection,
private val _density: Density,
private val textStyle: TextStyle,
Expand Down Expand Up @@ -689,8 +692,59 @@ internal open class CommandButtonLayoutManagerMedium(
popupActionRect = popupActionRect
)
}

override fun getActionKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
val hasIcon = (command.icon != null) || presentationModel.forceAllocateSpaceForIcon

// If the button shows icon, the action keytip is at the end edge of the icon. Otherwise,
// it is at the end edge of the full action click area.
if (layoutDirection == LayoutDirection.Ltr) {
val x = if (hasIcon) {
layoutInfo.iconRect.left + layoutInfo.iconRect.width
} else {
layoutInfo.actionClickArea.left + layoutInfo.actionClickArea.width
}
return Offset(
x = x,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
} else {
val x = if (hasIcon) {
layoutInfo.iconRect.left
} else {
layoutInfo.actionClickArea.left
}
return Offset(
x = x,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
}
}

override fun getPopupKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
return if (layoutDirection == LayoutDirection.Ltr) {
Offset(
x = layoutInfo.popupClickArea.left + layoutInfo.popupClickArea.width,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
} else {
Offset(
x = layoutInfo.popupClickArea.left,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
}
}
}

@AuroraInternalApi
internal class CommandButtonLayoutManagerMediumFitToIcon(
layoutDirection: LayoutDirection,
_density: Density,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.pushingpixels.aurora.component.layout

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.text.TextStyle
Expand Down Expand Up @@ -362,6 +363,42 @@ internal open class CommandButtonLayoutManagerSmall(
popupActionRect = popupActionRect
)
}

override fun getActionKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
return if (layoutDirection == LayoutDirection.Ltr) {
Offset(
x = layoutInfo.actionClickArea.left + layoutInfo.actionClickArea.width,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
} else {
Offset(
x = layoutInfo.actionClickArea.left,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
}
}

override fun getPopupKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
return if (layoutDirection == LayoutDirection.Ltr) {
Offset(
x = layoutInfo.popupClickArea.left + layoutInfo.popupClickArea.width,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
} else {
Offset(
x = layoutInfo.popupClickArea.left,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
}
}
}

internal class CommandButtonLayoutManagerSmallFitToIcon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.pushingpixels.aurora.component.layout

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.text.Paragraph
Expand Down Expand Up @@ -792,6 +793,56 @@ internal open class CommandButtonLayoutManagerTile(
popupActionRect = popupActionRect
)
}

override fun getActionKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
val hasIcon = (command.icon != null) || presentationModel.forceAllocateSpaceForIcon

// If the button shows icon, the action keytip is at the end edge of the icon. Otherwise,
// it is at the end edge of the full action click area.
if (layoutDirection == LayoutDirection.Ltr) {
val x = if (hasIcon) {
layoutInfo.iconRect.left + layoutInfo.iconRect.width
} else {
layoutInfo.actionClickArea.left + layoutInfo.actionClickArea.width
}
return Offset(
x = x,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
} else {
val x = if (hasIcon) {
layoutInfo.iconRect.left
} else {
layoutInfo.actionClickArea.left
}
return Offset(
x = x,
y = (layoutInfo.fullSize.height + layoutInfo.actionClickArea.height) / 2.0f
)
}
}

override fun getPopupKeyTipAnchorCenterPoint(
command: BaseCommand,
presentationModel: BaseCommandButtonPresentationModel,
layoutInfo: CommandButtonLayoutManager.CommandButtonLayoutInfo
): Offset {
return if (layoutDirection == LayoutDirection.Ltr) {
Offset(
x = layoutInfo.popupClickArea.left + layoutInfo.popupClickArea.width,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
} else {
Offset(
x = layoutInfo.popupClickArea.left,
y = (layoutInfo.fullSize.height + layoutInfo.popupClickArea.height) / 2.0f
)
}
}
}

internal class CommandButtonLayoutManagerTileFitToIcon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import org.pushingpixels.aurora.common.AuroraInternalApi
import org.pushingpixels.aurora.component.layout.*

interface CommandActionPreview {
Expand Down Expand Up @@ -187,6 +188,7 @@ abstract class CommandButtonPresentationState(val displayName: String) {
}

/** Medium state */
@OptIn(AuroraInternalApi::class)
val Medium: CommandButtonPresentationState =
object : CommandButtonPresentationState("Medium") {
override fun createLayoutManager(
Expand All @@ -205,6 +207,7 @@ abstract class CommandButtonPresentationState(val displayName: String) {
}

/** Fit-to-icon + medium state */
@OptIn(AuroraInternalApi::class)
val MediumFitToIcon: CommandButtonPresentationState =
object : CommandButtonPresentationState("Medium fit to icon") {
override fun createLayoutManager(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import org.pushingpixels.aurora.common.AuroraInternalApi
import org.pushingpixels.aurora.component.layout.CommandButtonLayoutManager
import org.pushingpixels.aurora.component.layout.CommandButtonLayoutManagerMedium
import org.pushingpixels.aurora.theming.IconFilterStrategy
Expand Down Expand Up @@ -50,6 +51,7 @@ data class CommandPopupMenuPresentationModel(
val toDismissOnCommandActivation: Boolean = true,
): BaseCommandPopupMenuPresentationModel

@OptIn(AuroraInternalApi::class)
private class PopupMenuCommandButtonLayoutManager(
layoutDirection: LayoutDirection,
density: Density,
Expand All @@ -74,6 +76,7 @@ private class PopupMenuCommandButtonLayoutManager(
}
}

@OptIn(AuroraInternalApi::class)
val DefaultCommandPopupMenuPresentationState: CommandButtonPresentationState =
object : CommandButtonPresentationState("Popup menu") {
override fun createLayoutManager(
Expand Down
Loading

0 comments on commit 36de6ae

Please sign in to comment.