Skip to content

Commit

Permalink
Adds a preference and an project preference page
Browse files Browse the repository at this point in the history
The preference is initialized with framework defaults (play.api.templates._, play.api.templates.PlayMagic._).
It can be overriden at the project level, in the project properties.
Changes are not applied directly, as we are currently lacking a real builder.

Fix #35.
  • Loading branch information
Luc Bourlier committed Apr 3, 2013
1 parent 5c7dd65 commit c97147b
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 12 deletions.
43 changes: 43 additions & 0 deletions org.scala-ide.play2/plugin.xml
Expand Up @@ -71,6 +71,9 @@
<initializer
class="org.scalaide.play2.templateeditor.properties.TemplateColourPreferenceInitializer">
</initializer>
<initializer
class="org.scalaide.play2.properties.PreferenceInitializer">
</initializer>
</extension>
<extension
point="org.eclipse.core.contenttype.contentTypes">
Expand Down Expand Up @@ -138,6 +141,46 @@
name="Format">
</command>
</extension>
<extension
point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="org.scalaide.play2.util.Play2PropertyTester"
id="org.scala-ide.play2.isJavaPlayProject"
namespace="org.scala-ide.play2.properties"
properties="isPlay2Project"
type="org.eclipse.jdt.core.IJavaProject">
</propertyTester>
<propertyTester
class="org.scalaide.play2.util.Play2PropertyTester"
id="org.scala-ide.play2.isPlayProject"
namespace="org.scala-ide.play2.properties"
properties="isPlay2Project"
type="org.eclipse.core.resources.IProject">
</propertyTester>
</extension>
<extension
point="org.eclipse.ui.propertyPages">
<page
class="org.scalaide.play2.properties.ProjectPropertyPage"
id="org.scala-ide.play2.projectPropertyPage"
name="Play2">
<enabledWhen>
<and>
<or>
<instanceof
value="org.eclipse.jdt.core.IJavaProject">
</instanceof>
<instanceof
value="org.eclipse.core.resources.IProject">
</instanceof>
</or>
<test
property="org.scala-ide.play2.properties.isPlay2Project">
</test>
</and>
</enabledWhen>
</page>
</extension>
<!--
<extension
point="org.eclipse.ui.editors.markerAnnotationSpecification">
Expand Down
4 changes: 2 additions & 2 deletions org.scala-ide.play2/src/org/scalaide/play2/PlayPlugin.scala
Expand Up @@ -10,7 +10,7 @@ import org.eclipse.core.runtime.Status
object PlayPlugin {
@volatile var plugin: PlayPlugin = _

private final val PluginId = "org.scala-ide.play2"
final val PluginId = "org.scala-ide.play2"
final val RouteFormatterMarginId = PluginId + ".routeeditor.margin"
final val TemplateExtension = "scala.html"

Expand Down Expand Up @@ -50,4 +50,4 @@ class PlayPlugin extends AbstractUIPlugin {
playProject <- asPlayProject(iProject)
} playProject.initialize()
}
}
}
8 changes: 8 additions & 0 deletions org.scala-ide.play2/src/org/scalaide/play2/PlayProject.scala
Expand Up @@ -8,10 +8,18 @@ import org.eclipse.core.resources.IFile
import org.scalaide.play2.templateeditor.TemplateCompilationUnit
import org.scalaide.play2.templateeditor.compiler.TemplatePresentationCompiler
import org.scalaide.play2.util.AutoHashMap
import org.eclipse.ui.preferences.ScopedPreferenceStore
import org.eclipse.core.resources.ProjectScope
import org.scalaide.play2.util.SyncedScopedPreferenceStore
import org.eclipse.jface.preference.IPreferenceStore

class PlayProject private (val scalaProject: ScalaProject) {
private val presentationCompiler = new TemplatePresentationCompiler(this)

val cachedPreferenceStore = new SyncedScopedPreferenceStore(scalaProject.underlying, PlayPlugin.PluginId)

def generateScopedPreferenceStore: IPreferenceStore = new ScopedPreferenceStore(new ProjectScope(scalaProject.underlying), PlayPlugin.PluginId)

def withPresentationCompiler[T](op: TemplatePresentationCompiler => T): T = {
op(presentationCompiler)
}
Expand Down
Expand Up @@ -16,6 +16,41 @@ import org.eclipse.ui.IWorkbenchPreferencePage
import org.eclipse.ui.dialogs.PropertyPage
import org.scalaide.play2.PlayPlugin

object PlayPreferences {

/** Preference containing the list of import to automatically add to the generate template code.
* The data is stored as the string which will be added to the generated source (to not recreate
* it everytime). The empty String represent an empty import list.
* [[org.scalaide.play2.properties.PlayPreferences.serializeImports]] and [[org.scalaide.play2.properties.PlayPreferences.deserializeImports]]
* need to be used when converting the preference value to/from Array[String].
*/
final val TemplateImports = "templateImports"

// Regex used for the operations on the templateImports preference.
private val importsRegex = "import ([^\n]+)\n".r

/** @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
*/
def serializeImports(entries: Array[String]): String = {
if (entries.length == 0) {
""
} else {
entries.mkString("import ", "\nimport ", "\n")
}
}

/** @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
*/
def deserializeImports(s: String): Array[String] = {
if (s.length == 0) {
new Array(0)
} else {
importsRegex.findAllIn(s).matchData.map(m => m.group(1)).toArray
}
}

}

class PlayPreferences extends PropertyPage with IWorkbenchPreferencePage with EclipseSettings
with ScalaPluginPreferencePage with HasLogger {

Expand Down
@@ -0,0 +1,12 @@
package org.scalaide.play2.properties

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer
import org.scalaide.play2.PlayPlugin

class PreferenceInitializer extends AbstractPreferenceInitializer {

override def initializeDefaultPreferences() {
PlayPlugin.prefStore.setDefault(PlayPreferences.TemplateImports, "import play.api.templates._\nimport play.api.templates.PlayMagic._\n")
}

}
@@ -0,0 +1,83 @@
package org.scalaide.play2.properties

import org.eclipse.core.resources.IProject
import org.eclipse.core.runtime.IAdaptable
import org.eclipse.jdt.core.IJavaProject
import org.eclipse.jface.dialogs.IInputValidator
import org.eclipse.jface.dialogs.InputDialog
import org.eclipse.jface.preference.FieldEditorPreferencePage
import org.eclipse.jface.preference.IPreferenceStore
import org.eclipse.jface.preference.ListEditor
import org.eclipse.jface.window.Window
import org.eclipse.swt.widgets.Composite
import org.eclipse.swt.widgets.Display
import org.eclipse.ui.IWorkbenchPropertyPage
import org.scalaide.play2.PlayPlugin

/** Preference page displayed in the property dialog of (play) projects.
* Used from the UI thread.
*/
class ProjectPropertyPage extends FieldEditorPreferencePage(FieldEditorPreferencePage.GRID) with IWorkbenchPropertyPage {

/** Preference field to display the list of extra imports.
*/
private class ImportsFieldEditor(name: String, labelText: String, parent: Composite) extends ListEditor(name, labelText, parent) {

override protected def createList(entries: Array[String]): String =
PlayPreferences.serializeImports(entries)

override protected def parseString(s: String): Array[String] =
PlayPreferences.deserializeImports(s)

override protected def getNewInputObject(): String = {

val dlg = new InputDialog(
Display.getCurrent().getActiveShell(),
"Play template import",
"Enter an import value:",
"com.example._",
new IInputValidator {
def isValid(text: String) = null
});

if (dlg.open() == Window.OK) {
dlg.getValue()
} else {
null
}
}

}

// The preference store being edited.
// The data require to get the store is provided by the workbench during the page lifecycle.
private var prefStore: IPreferenceStore = _

// Members declared in org.eclipse.jface.preference.FieldEditorPreferencePage

override def createFieldEditors() {
addField(new ImportsFieldEditor(PlayPreferences.TemplateImports, "Template default imports", getFieldEditorParent()))
}

// Members declared in org.eclipse.ui.IWorkbenchPropertyPage

// doesn't seem to be a real function for this method.
// It looks like it leaked from the implementation of PropertyPage.
override def getElement(): IAdaptable = null

override def setElement(element: IAdaptable) {
prefStore = element match {
case project: IProject =>
PlayPlugin.plugin.asPlayProject(project).get.generateScopedPreferenceStore
case project: IJavaProject =>
PlayPlugin.plugin.asPlayProject(project.getProject()).get.generateScopedPreferenceStore
}
}

// ----

override def doGetPreferenceStore(): IPreferenceStore = {
prefStore
}

}
Expand Up @@ -9,25 +9,21 @@ import play.templates.ScalaTemplateCompiler
import play.templates.ScalaTemplateCompiler._
import play.templates.TemplateCompilationError
import scalax.file.Path
import org.scalaide.play2.properties.PlayPreferences
import scala.tools.eclipse.logging.HasLogger

/**
* a helper for using template compiler
*/
object CompilerUsing extends HasLogger {
val templateCompiler = ScalaTemplateCompiler
val additionalImports = """import play.templates._
import play.templates.TemplateMagic._
import play.api.templates._
import play.api.templates.PlayMagic._
val additionalImports = """
import models._
import controllers._
import play.api.i18n._
import play.api.mvc._
import play.api.data._
import views.html._"""
import views.html._
"""

/**
* invokes compile method of template compiler and returns generated source object or
Expand All @@ -39,7 +35,7 @@ import views.html._"""
logger.debug(s"Template file '${source.getAbsolutePath}' must be located in '$sourcePath' or one of its subfolders!")

Try {
templateCompiler.compileVirtual(content, source, playProject.sourceDir, "play.api.templates.Html", "play.api.templates.HtmlFormat", additionalImports)
templateCompiler.compileVirtual(content, source, playProject.sourceDir, "play.api.templates.Html", "play.api.templates.HtmlFormat", additionalImports + playProject.cachedPreferenceStore.getString(PlayPreferences.TemplateImports))
} recoverWith {
case TemplateCompilationError(source, message, line, column) =>
val offset = PositionHelper.convertLineColumnToOffset(content, line, column)
Expand Down Expand Up @@ -100,4 +96,4 @@ object PositionHelper {
}
}
}
}
}
@@ -0,0 +1,36 @@
package org.scalaide.play2.util

import org.eclipse.core.expressions.PropertyTester
import org.eclipse.core.resources.IProject
import org.scalaide.play2.PlayPlugin
import org.eclipse.jdt.core.IJavaProject

object Play2PropertyTester {
final val IsPlayProject = "isPlay2Project"
}

/** Eclipse property tester. Can check if a project is a play2 project.
*/
class Play2PropertyTester() extends PropertyTester {

// from IPropertyTester

override def test(receiver: Any, property: String, args: Array[Object], expectedValue: Any): Boolean = {
import Play2PropertyTester._

property match {
case IsPlayProject =>
receiver match {
case project: IProject =>
PlayPlugin.plugin.asPlayProject(project).isDefined
case project: IJavaProject =>
PlayPlugin.plugin.asPlayProject(project.getProject()).isDefined
case _ =>
false
}
case _ =>
false
}
}

}
@@ -0,0 +1,16 @@
package org.scalaide.play2.util

import org.eclipse.core.resources.IProject
import org.eclipse.core.resources.ProjectScope
import org.eclipse.ui.preferences.ScopedPreferenceStore

class SyncedScopedPreferenceStore(project: IProject, pluginId: String) {

private val preferenceStore = new ScopedPreferenceStore(new ProjectScope(project), pluginId)

def getString(name: String): String = {
preferenceStore.synchronized {
preferenceStore.getString(name)
}
}
}

0 comments on commit c97147b

Please sign in to comment.