<commit_before>package at.cpickl.gadsu.client.view.detail

import at.cpickl.gadsu.appointment.view.AppoinmentsInClientView
import at.cpickl.gadsu.client.Client
import at.cpickl.gadsu.client.Contact
import at.cpickl.gadsu.client.CurrentClient
import at.cpickl.gadsu.client.SaveClientEvent
import at.cpickl.gadsu.client.forClient
import at.cpickl.gadsu.development.debugColor
import at.cpickl.gadsu.service.CurrentEvent
import at.cpickl.gadsu.service.LOG
import at.cpickl.gadsu.service.Logged
import at.cpickl.gadsu.service.SuggesterController
import at.cpickl.gadsu.treatment.inclient.TreatmentsInClientView
import at.cpickl.gadsu.view.SwingFactory
import at.cpickl.gadsu.view.ViewNames
import at.cpickl.gadsu.view.components.newPersistableEventButton
import at.cpickl.gadsu.view.components.panels.GridPanel
import at.cpickl.gadsu.view.logic.ModificationAware
import at.cpickl.gadsu.view.logic.ModificationChecker
import at.cpickl.gadsu.view.swing.changeSize
import at.cpickl.gadsu.view.swing.enforceWidth
import at.cpickl.gadsu.view.swing.transparent
import com.google.common.eventbus.EventBus
import com.google.common.eventbus.Subscribe
import com.google.inject.Inject
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import java.awt.Dimension
import java.awt.GridBagConstraints
import javax.swing.JButton
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JTabbedPane

interface ClientDetailView {

    fun readClient(): Client
//    fun changeClient(client: Client)
    fun isModified(): Boolean
//    fun changeImage(newImage: MyImage)
    fun focusFirst()
    fun asComponent(): Component
    fun closePreparations()
}

@Logged
open class SwingClientDetailView @Inject constructor(
        swing: SwingFactory,
        bus: EventBus,
        private val currentClient: CurrentClient,
        appointmentsSubView: AppoinmentsInClientView, // passed through to TabMain
        treatmentSubview: TreatmentsInClientView, // passed through to TabMain
        suggester: SuggesterController // passed through to TabMain
//        imagePickerFactory: ImagePickerFactory,
//        prefs: Prefs
) : GridPanel(), ClientDetailView, ModificationAware {
    private val log = LOG(javaClass)

    private val btnSave = swing.newPersistableEventButton(ViewNames.Client.SaveButton, { SaveClientEvent() })
    private val btnCancel = JButton("Abbrechen")
    // attention: must come AFTER list of buttons due to hacky design nature ;)

    private val modificationChecker = ModificationChecker(this, btnSave, btnCancel)

    private val tabMain = ClientTabMain(currentClient.data, modificationChecker, appointmentsSubView, treatmentSubview, suggester)
//            imagePickerFactory.create(imageViewNamePrefix, prefs.clientPictureDefaultFolder)
    private val tabTexts = ClientTabTexts(modificationChecker, bus)
    private val tabTcm = ClientTabTcm(currentClient.data, modificationChecker, bus)

    private val allTabs = arrayOf(tabMain, tabTexts, tabTcm)
    init {
        modificationChecker.disableAll()

        btnCancel.name = ViewNames.Client.CancelButton
        btnCancel.addActionListener {
            log.debug("btnCancel clicked")
            updateFields()
        }
        val newSize = Dimension(btnSave.preferredSize.width + 20, btnSave.preferredSize.height)
        btnSave.changeSize(newSize)
        btnCancel.changeSize(newSize)

        initLayout()
    }

    override fun closePreparations() {
        tabMain.inpBirthday.hidePopup()
    }

    private fun initLayout() {
        c.fill = GridBagConstraints.BOTH
        c.weightx = 1.0
        c.weighty = 1.0
        add(createTabbedPane())

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.CENTER
        c.weightx = 1.0
        c.weighty = 0.0
        add(createButtonPanel())
    }

    private fun createTabbedPane(): JTabbedPane {
        val tabbed = JTabbedPane(JTabbedPane.NORTH, JTabbedPane.SCROLL_TAB_LAYOUT)
        tabbed.isOpaque = false
        tabbed.name = ViewNames.Client.TabbedPane
        var i: Int = 0
        allTabs.forEach {
            val tabContent: Component = if (it.scrolled) JScrollPane(it.asComponent()).transparent() else it.asComponent()
            tabbed.addTab("<html><body><table width='100'><span style='align:center'>${it.title}</span></table></body></html>", tabContent)
            tabbed.setTabComponentAt(i++, JLabel(it.title, JLabel.CENTER).enforceWidth(100))
        }
        return tabbed
    }

    private fun createButtonPanel(): JPanel {
        val buttonPanel = JPanel(BorderLayout())
        buttonPanel.transparent()
        buttonPanel.debugColor = Color.BLUE
        buttonPanel.add(btnSave, BorderLayout.WEST)
        buttonPanel.add(btnCancel, BorderLayout.EAST)
        return buttonPanel
    }

    override fun readClient(): Client {
        log.trace("readClient()");
        return Client(
                currentClient.data.id,
                currentClient.data.created,
                tabMain.inpFirstName.text,
                tabMain.inpLastName.text,

                Contact(
                        mail = tabMain.inpMail.text,<commit_msg>#33 all tabs now accessible via shortcuts CTRL (or META on mac) + {1, 2, 3}<commit_after>package at.cpickl.gadsu.client.view.detail

import at.cpickl.gadsu.IS_OS_MAC
import at.cpickl.gadsu.appointment.view.AppoinmentsInClientView
import at.cpickl.gadsu.client.Client
import at.cpickl.gadsu.client.Contact
import at.cpickl.gadsu.client.CurrentClient
import at.cpickl.gadsu.client.SaveClientEvent
import at.cpickl.gadsu.client.forClient
import at.cpickl.gadsu.development.debugColor
import at.cpickl.gadsu.service.CurrentEvent
import at.cpickl.gadsu.service.LOG
import at.cpickl.gadsu.service.Logged
import at.cpickl.gadsu.service.SuggesterController
import at.cpickl.gadsu.treatment.inclient.TreatmentsInClientView
import at.cpickl.gadsu.view.SwingFactory
import at.cpickl.gadsu.view.ViewNames
import at.cpickl.gadsu.view.components.newPersistableEventButton
import at.cpickl.gadsu.view.components.panels.GridPanel
import at.cpickl.gadsu.view.logic.ModificationAware
import at.cpickl.gadsu.view.logic.ModificationChecker
import at.cpickl.gadsu.view.swing.changeSize
import at.cpickl.gadsu.view.swing.enforceWidth
import at.cpickl.gadsu.view.swing.transparent
import com.google.common.eventbus.EventBus
import com.google.common.eventbus.Subscribe
import com.google.inject.Inject
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import java.awt.Dimension
import java.awt.GridBagConstraints
import java.awt.KeyboardFocusManager
import java.awt.event.KeyEvent
import javax.swing.JButton
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JTabbedPane

interface ClientDetailView {

    fun readClient(): Client
//    fun changeClient(client: Client)
    fun isModified(): Boolean
//    fun changeImage(newImage: MyImage)
    fun focusFirst()
    fun asComponent(): Component
    fun closePreparations()
}

@Logged
open class SwingClientDetailView @Inject constructor(
        swing: SwingFactory,
        bus: EventBus,
        private val currentClient: CurrentClient,
        appointmentsSubView: AppoinmentsInClientView, // passed through to TabMain
        treatmentSubview: TreatmentsInClientView, // passed through to TabMain
        suggester: SuggesterController // passed through to TabMain
//        imagePickerFactory: ImagePickerFactory,
//        prefs: Prefs
) : GridPanel(), ClientDetailView, ModificationAware {
    private val log = LOG(javaClass)

    private val btnSave = swing.newPersistableEventButton(ViewNames.Client.SaveButton, { SaveClientEvent() })
    private val btnCancel = JButton("Abbrechen")
    // attention: must come AFTER list of buttons due to hacky design nature ;)

    private val modificationChecker = ModificationChecker(this, btnSave, btnCancel)

    private val tabMain = ClientTabMain(currentClient.data, modificationChecker, appointmentsSubView, treatmentSubview, suggester)
//            imagePickerFactory.create(imageViewNamePrefix, prefs.clientPictureDefaultFolder)
    private val tabTexts = ClientTabTexts(modificationChecker, bus)
    private val tabTcm = ClientTabTcm(currentClient.data, modificationChecker, bus)

    private val tabbedPane = JTabbedPane(JTabbedPane.NORTH, JTabbedPane.SCROLL_TAB_LAYOUT)
    private val allTabs = arrayOf(tabMain, tabTexts, tabTcm)
    init {
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher { event ->

                    val handled: Boolean
                    val commandDown = if (IS_OS_MAC) {
                        event.isMetaDown
                    } else {
                        event.isControlDown
                    }
                    if (commandDown) {
                        val newTab: JPanel? = when (event.keyCode) {
                            KeyEvent.VK_1 -> tabMain
                            KeyEvent.VK_2 -> tabTexts
                            KeyEvent.VK_3 -> tabTcm
                            else -> null
                        }
                        if (newTab != null && newTab != tabbedPane.selectedComponent) {
                            handled = true
                            log.trace("Changing selected tab to: {}", newTab)
                            tabbedPane.selectedComponent = newTab
                        } else {
                            handled = false
                        }
                    } else {
                        handled = false
                    }
                    handled
                }

        modificationChecker.disableAll()

        btnCancel.name = ViewNames.Client.CancelButton
        btnCancel.addActionListener {
            log.debug("btnCancel clicked")
            updateFields()
        }
        val newSize = Dimension(btnSave.preferredSize.width + 20, btnSave.preferredSize.height)
        btnSave.changeSize(newSize)
        btnCancel.changeSize(newSize)

        initLayout()
    }

    override fun closePreparations() {
        tabMain.inpBirthday.hidePopup()
    }

    private fun initLayout() {
        c.fill = GridBagConstraints.BOTH
        c.weightx = 1.0
        c.weighty = 1.0
        add(initTabbedPane())

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.CENTER
        c.weightx = 1.0
        c.weighty = 0.0
        add(createButtonPanel())
    }

    private fun initTabbedPane(): JTabbedPane {
        tabbedPane.isOpaque = false
        tabbedPane.name = ViewNames.Client.TabbedPane
        var i: Int = 0
        allTabs.forEach {
            val tabContent: Component = if (it.scrolled) JScrollPane(it.asComponent()).transparent() else it.asComponent()
            tabbedPane.addTab("<html><body><table width='100'><span style='align:center'>${it.title}</span></table></body></html>", tabContent)
            tabbedPane.setTabComponentAt(i++, JLabel(it.title, JLabel.CENTER).enforceWidth(100))
        }
        return tabbedPane
    }

    private fun createButtonPanel(): JPanel {
        val buttonPanel = JPanel(BorderLayout())
        buttonPanel.transparent()
        buttonPanel.debugColor = Color.BLUE
        buttonPanel.add(btnSave, BorderLayout.WEST)
        buttonPanel.add(btnCancel, BorderLayout.EAST)
        return buttonPanel
    }

    override fun readClient(): Client {
        log.trace("readClient()");
        return Client(
                currentClient.data.id,
                currentClient.data.created,
                tabMain.inpFirstName.text,
                tabMain.inpLastName.text,

                Contact(
                        mail = tabMain.inpMail.text,
{'fraction_non_alphanumeric': 0.08781725888324873, 'fraction_numerical': 0.003553299492385787, 'mean_word_length': 2.7538901238488407, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5010469', 'n_tokens_mistral': 3518, 'n_tokens_neox': 3418, 'n_words': 653}