Commit 0835821a authored by Sawyer Blatz's avatar Sawyer Blatz Committed by Sebastian Kaspari
Browse files

Closes #2615: Adds titleView to DisplayToolbar

parent caaf992d
Loading
Loading
Loading
Loading
+25 −0
Original line number Original line Diff line number Diff line
@@ -192,6 +192,15 @@ class BrowserToolbar @JvmOverloads constructor(
            displayToolbar.progressBarGravity = value
            displayToolbar.progressBarGravity = value
        }
        }


    /**
     * Sets the colour of the text for title displayed in the toolbar.
     */
    var titleColor: Int
        get() = displayToolbar.urlView.currentTextColor
        set(value) {
            displayToolbar.titleView.setTextColor(value)
        }

    /**
    /**
     * Sets the colour of the text for the URL/search term displayed in the toolbar.
     * Sets the colour of the text for the URL/search term displayed in the toolbar.
     */
     */
@@ -202,6 +211,15 @@ class BrowserToolbar @JvmOverloads constructor(
            editToolbar.urlView.setTextColor(value)
            editToolbar.urlView.setTextColor(value)
        }
        }


    /**
     * Sets the size of the text for the title displayed in the toolbar.
     */
    var titleTextSize: Float
        get() = displayToolbar.titleView.textSize
        set(value) {
            displayToolbar.titleView.textSize = value
        }

    /**
    /**
     * Sets the size of the text for the URL/search term displayed in the toolbar.
     * Sets the size of the text for the URL/search term displayed in the toolbar.
     */
     */
@@ -296,6 +314,13 @@ class BrowserToolbar @JvmOverloads constructor(
    private var searchTerms: String = ""
    private var searchTerms: String = ""
    private var urlCommitListener: ((String) -> Boolean)? = null
    private var urlCommitListener: ((String) -> Boolean)? = null


    override var title: String = ""
        set(value) {
            displayToolbar.updateTitle(value)

            field = value
        }

    override var url: CharSequence = ""
    override var url: CharSequence = ""
        set(value) {
        set(value) {
            // We update the display toolbar immediately. We do not do that for the edit toolbar to not
            // We update the display toolbar immediately. We do not do that for the edit toolbar to not
+57 −5
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@ import android.support.v4.content.ContextCompat
import android.support.v7.widget.AppCompatImageButton
import android.support.v7.widget.AppCompatImageButton
import android.support.v7.widget.AppCompatImageView
import android.support.v7.widget.AppCompatImageView
import android.support.v7.widget.AppCompatTextView
import android.support.v7.widget.AppCompatTextView
import android.text.TextUtils
import android.util.TypedValue
import android.util.TypedValue
import android.view.Gravity
import android.view.Gravity
import android.view.View
import android.view.View
@@ -66,7 +67,7 @@ import mozilla.components.ui.icons.R.drawable.mozac_ic_lock
 *
 *
 */
 */
@SuppressLint("ViewConstructor") // This view is only instantiated in code
@SuppressLint("ViewConstructor") // This view is only instantiated in code
@Suppress("LargeClass")
@Suppress("LargeClass", "TooManyFunctions")
internal class DisplayToolbar(
internal class DisplayToolbar(
    context: Context,
    context: Context,
    val toolbar: BrowserToolbar
    val toolbar: BrowserToolbar
@@ -89,6 +90,16 @@ internal class DisplayToolbar(
        setOnClickListener(null)
        setOnClickListener(null)
    }
    }


    internal val titleView = AppCompatTextView(context).apply {
        id = R.id.mozac_browser_toolbar_title_view
        gravity = Gravity.CENTER_VERTICAL
        textSize = URL_TEXT_SIZE
        visibility = View.GONE
        ellipsize = TextUtils.TruncateAt.END

        setSingleLine(true)
    }

    internal val urlView = AppCompatTextView(context).apply {
    internal val urlView = AppCompatTextView(context).apply {
        id = R.id.mozac_browser_toolbar_url_view
        id = R.id.mozac_browser_toolbar_url_view
        gravity = Gravity.CENTER_VERTICAL
        gravity = Gravity.CENTER_VERTICAL
@@ -195,11 +206,20 @@ internal class DisplayToolbar(


    init {
    init {
        addView(siteSecurityIconView)
        addView(siteSecurityIconView)
        addView(titleView)
        addView(urlView)
        addView(urlView)
        addView(menuView)
        addView(menuView)
        addView(progressView)
        addView(progressView)
    }
    }


    /**
     * Updates the title to be displayed.
     */
    fun updateTitle(title: String) {
        titleView.text = title
        titleView.visibility = if (title.isEmpty()) View.GONE else View.VISIBLE
    }

    /**
    /**
     * Updates the URL to be displayed.
     * Updates the URL to be displayed.
     */
     */
@@ -306,7 +326,8 @@ internal class DisplayToolbar(
        val height = MeasureSpec.getSize(heightMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)


        val fixedHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
        val fixedHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)

        val halfFixedHeightSpec = MeasureSpec
                .makeMeasureSpec(height / MEASURED_HEIGHT_DENOMINATOR, MeasureSpec.EXACTLY)
        setMeasuredDimension(width, height)
        setMeasuredDimension(width, height)


        // The icon and menu fill the whole height and have a square shape
        // The icon and menu fill the whole height and have a square shape
@@ -325,7 +346,15 @@ internal class DisplayToolbar(
        val urlWidth = (width - iconSize - browserActionsWidth - pageActionsWidth -
        val urlWidth = (width - iconSize - browserActionsWidth - pageActionsWidth -
            menuWidth - navigationActionsWidth - 2 * urlBoxMargin)
            menuWidth - navigationActionsWidth - 2 * urlBoxMargin)
        val urlWidthSpec = MeasureSpec.makeMeasureSpec(urlWidth, MeasureSpec.EXACTLY)
        val urlWidthSpec = MeasureSpec.makeMeasureSpec(urlWidth, MeasureSpec.EXACTLY)

        if (titleView.isVisible()) {
            // With a title view, the url and title split the rest of the space vertically
            titleView.measure(urlWidthSpec, halfFixedHeightSpec)
            urlView.measure(urlWidthSpec, halfFixedHeightSpec)
        } else {
            // With no title view, the url view takes up the rest of the space
            urlView.measure(urlWidthSpec, fixedHeightSpec)
            urlView.measure(urlWidthSpec, fixedHeightSpec)
        }


        val progressHeightSpec = MeasureSpec.makeMeasureSpec(resources.pxToDp(PROGRESS_BAR_HEIGHT_DP),
        val progressHeightSpec = MeasureSpec.makeMeasureSpec(resources.pxToDp(PROGRESS_BAR_HEIGHT_DP),
                MeasureSpec.EXACTLY)
                MeasureSpec.EXACTLY)
@@ -427,10 +456,32 @@ internal class DisplayToolbar(
        //   | navigation  | icon | url       [ page    ] | browser  | menu |
        //   | navigation  | icon | url       [ page    ] | browser  | menu |
        //   |   actions   |      |           [ actions ] | actions  |      |
        //   |   actions   |      |           [ actions ] | actions  |      |
        //   +-------------+------+-----------------------+----------+------+
        //   +-------------+------+-----------------------+----------+------+

        val iconWidth = if (siteSecurityIconView.isVisible()) siteSecurityIconView.measuredWidth else 0
        val iconWidth = if (siteSecurityIconView.isVisible()) siteSecurityIconView.measuredWidth else 0
        val urlLeft = navigationActionsWidth + iconWidth + urlBoxMargin
        val urlLeft = navigationActionsWidth + iconWidth + urlBoxMargin

        // If the titleView is visible, it will appear above the URL:
        //   +-------------+------+-----------------------+----------+------+
        //   | navigation  | icon |  title       [ page    ] | browser  | menu |
        //   |   actions   |      |  url         [ actions ] | actions  |      |
        //   +-------------+------+-----------------------+----------+------+
        if (titleView.isVisible()) {
            val totalTextHeights = urlView.measuredHeight + titleView.measuredHeight
            val totalAvailablePadding = height - totalTextHeights
            val padding = totalAvailablePadding / MEASURED_HEIGHT_DENOMINATOR

            titleView.layout(
                    urlLeft,
                    padding,
                    urlLeft + titleView.measuredWidth,
                    padding + titleView.measuredHeight)
            urlView.layout(
                    urlLeft,
                    padding + titleView.measuredHeight,
                    urlLeft + urlView.measuredWidth,
                    padding + titleView.measuredHeight + urlView.measuredHeight)
        } else {
            urlView.layout(urlLeft, 0, urlLeft + urlView.measuredWidth, measuredHeight)
            urlView.layout(urlLeft, 0, urlLeft + urlView.measuredWidth, measuredHeight)
        }


        // The progress bar by default is going to be drawn at the bottom of the toolbar, top if defined:
        // The progress bar by default is going to be drawn at the bottom of the toolbar, top if defined:
        progressView.layout(
        progressView.layout(
@@ -449,6 +500,7 @@ internal class DisplayToolbar(
    }
    }


    companion object {
    companion object {
        internal const val MEASURED_HEIGHT_DENOMINATOR = 2
        internal const val URL_FADING_EDGE_SIZE_DP = 24
        internal const val URL_FADING_EDGE_SIZE_DP = 24


        const val BOTTOM_PROGRESS_BAR = 0
        const val BOTTOM_PROGRESS_BAR = 0
+1 −0
Original line number Original line Diff line number Diff line
@@ -6,6 +6,7 @@
  -->
  -->


<resources>
<resources>
    <item name="mozac_browser_toolbar_title_view" type="id"/>
    <item name="mozac_browser_toolbar_url_view" type="id"/>
    <item name="mozac_browser_toolbar_url_view" type="id"/>
    <item name="mozac_browser_toolbar_edit_url_view" type="id"/>
    <item name="mozac_browser_toolbar_edit_url_view" type="id"/>
    <item name="mozac_browser_toolbar_clear_view" type="id"/>
    <item name="mozac_browser_toolbar_clear_view" type="id"/>
+39 −0
Original line number Original line Diff line number Diff line
@@ -742,6 +742,45 @@ class BrowserToolbarTest {
        assertEquals(12f, toolbar.editToolbar.urlView.textSize)
        assertEquals(12f, toolbar.editToolbar.urlView.textSize)
    }
    }


    @Test
    fun `titleTextSize changes display titleView`() {
        val toolbar = BrowserToolbar(context)

        assertTrue(toolbar.displayToolbar.titleView.textSize != 12f)

        toolbar.titleTextSize = 12f

        assertEquals(12f, toolbar.displayToolbar.titleView.textSize)
    }

    @Test
    fun `titleTextColor changes display titleView`() {
        val toolbar = BrowserToolbar(context)

        toolbar.titleColor = R.color.photonBlue40

        assertEquals(R.color.photonBlue40, toolbar.displayToolbar.titleView.currentTextColor)
    }

    @Test
    fun `titleView visibility is based on being set`() {
        val toolbar = BrowserToolbar(context)

        assertEquals(toolbar.displayToolbar.titleView.visibility, View.GONE)
        toolbar.title = "Mozilla"
        assertEquals(toolbar.displayToolbar.titleView.visibility, View.VISIBLE)
        toolbar.title = ""
        assertEquals(toolbar.displayToolbar.titleView.visibility, View.GONE)
    }

    @Test
    fun `titleView text is set properly`() {
        val toolbar = BrowserToolbar(context)

        toolbar.title = "Mozilla"
        assertEquals(toolbar.displayToolbar.titleView.text, "Mozilla")
    }

    @Test
    @Test
    fun `typeface changes edit and display urlView`() {
    fun `typeface changes edit and display urlView`() {
        val toolbar = BrowserToolbar(context)
        val toolbar = BrowserToolbar(context)
+96 −0
Original line number Original line Diff line number Diff line
@@ -605,6 +605,102 @@ class DisplayToolbarTest {
        assertEquals(624, viewRect.width())
        assertEquals(624, viewRect.width())
    }
    }


    @Test
    fun `titleView does not display when there is no title text`() {
        val toolbar = mock(BrowserToolbar::class.java)
        val displayToolbar = DisplayToolbar(context, toolbar)

        val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
        val heightSpec = View.MeasureSpec.makeMeasureSpec(200, View.MeasureSpec.AT_MOST)

        displayToolbar.measure(widthSpec, heightSpec)
        displayToolbar.layout(0, 0, 1024, 200)

        val urlView = displayToolbar.urlView
        val titleView = displayToolbar.titleView

        val urlViewRect = Rect(urlView.left, urlView.top, urlView.right, urlView.bottom)
        val titleViewRect = Rect(titleView.left, titleView.top, titleView.right, titleView.bottom)

        assertTrue(urlViewRect.width() > 0)
        assertTrue(urlViewRect.height() > 0)

        assertTrue(titleViewRect.width() == 0)
        assertTrue(titleViewRect.height() == 0)
        assertEquals(titleView.visibility, View.GONE)
    }

    @Test
    fun `titleView is properly laid out when there is title text`() {
        val toolbar = mock(BrowserToolbar::class.java)
        val displayToolbar = DisplayToolbar(context, toolbar)

        displayToolbar.updateTitle("Mozilla")
        assertEquals(displayToolbar.titleView.visibility, View.VISIBLE)

        val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
        val heightSpec = View.MeasureSpec.makeMeasureSpec(200, View.MeasureSpec.AT_MOST)

        displayToolbar.measure(widthSpec, heightSpec)
        displayToolbar.layout(0, 0, 1024, 200)

        val urlView = displayToolbar.urlView
        val titleView = displayToolbar.titleView

        val urlViewRect = Rect(urlView.left, urlView.top, urlView.right, urlView.bottom)
        val titleViewRect = Rect(titleView.left, titleView.top, titleView.right, titleView.bottom)

        assertTrue(urlViewRect.width() > 0)
        assertTrue(urlViewRect.height() > 0)

        assertTrue(titleViewRect.width() > 0)
        assertTrue(titleViewRect.height() > 0)

        val totalTextHeights = urlViewRect.height() + titleViewRect.height()
        val totalAvailablePadding = 200 - totalTextHeights
        val padding = totalAvailablePadding / DisplayToolbar.MEASURED_HEIGHT_DENOMINATOR

        assertTrue(titleViewRect.left == urlViewRect.left)
        assertTrue(titleViewRect.top == padding)
        assertTrue(titleViewRect.right == urlViewRect.right)
        assertTrue(titleViewRect.bottom == padding + titleViewRect.height())
    }

    @Test
    fun `urlView is properly laid out when a title is shown`() {
        val toolbar = mock(BrowserToolbar::class.java)
        val displayToolbar = DisplayToolbar(context, toolbar)

        displayToolbar.updateTitle("Mozilla")

        val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
        val heightSpec = View.MeasureSpec.makeMeasureSpec(200, View.MeasureSpec.AT_MOST)

        displayToolbar.measure(widthSpec, heightSpec)
        displayToolbar.layout(0, 0, 1024, 200)

        val urlView = displayToolbar.urlView
        val titleView = displayToolbar.titleView

        val titleViewRect = Rect(titleView.left, titleView.top, titleView.right, titleView.bottom)
        val urlViewRect = Rect(urlView.left, urlView.top, urlView.right, urlView.bottom)

        val totalTextHeights = urlViewRect.height() + titleViewRect.height()
        val totalAvailablePadding = 200 - totalTextHeights
        val padding = totalAvailablePadding / DisplayToolbar.MEASURED_HEIGHT_DENOMINATOR

        assertTrue(urlViewRect.width() > 0)
        assertTrue(urlViewRect.height() > 0)

        assertTrue(titleViewRect.width() > 0)
        assertTrue(titleViewRect.height() > 0)

        assertTrue(urlViewRect.left == titleViewRect.left)
        assertTrue(urlViewRect.top == padding + titleViewRect.height())
        assertTrue(urlViewRect.right == titleView.right)
        assertTrue(urlViewRect.bottom == padding + titleViewRect.height() + urlViewRect.height())
    }

    @Test
    @Test
    fun `toolbar only switches to editing mode if onUrlClicked returns true`() {
    fun `toolbar only switches to editing mode if onUrlClicked returns true`() {
        val toolbar = mock(BrowserToolbar::class.java)
        val toolbar = mock(BrowserToolbar::class.java)
Loading