Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/__init__.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/__init__.py	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/__init__.py	(revision 616)
@@ -0,0 +1,1 @@
+#
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configlet.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configlet.py	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configlet.py	(revision 616)
@@ -0,0 +1,90 @@
+from zope.interface import Interface
+from zope.component import adapts
+from zope.interface import implements
+from zope import schema
+from zope.app.form import CustomWidgetFactory
+from zope.app.form.browser import ObjectWidget
+from zope.app.form.browser import ListSequenceWidget
+from zope.formlib import form
+
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+
+from plone.app.controlpanel.form import ControlPanelForm
+
+from quintagroup.portlet.static import StaticStylishPortletMessageFactory as _
+from quintagroup.portlet.static.utils import getVocabulary
+
+
+class IValueTitlePair(Interface):
+    value = schema.TextLine(title=u"value", required=True)
+    title = schema.TextLine(title=u"title", required=False)
+
+class ValueTitlePair(object):
+    implements(IValueTitlePair)
+    def __init__(self, value='', title=''):
+        self.value = value
+        self.title = title
+
+class IStaticStylishPortletPanelSchema(Interface):
+
+    portlet_dropdown = schema.List(
+        title=_(u'Dropdown select'),
+        description=_(u"These entries are used for generating dropdown select "
+                      "for static stylish portlet. Note: pipe (|) "
+                      "symbol is not allowed in the value field."),
+        value_type=schema.Object(IValueTitlePair, title=u"entry"),
+        required=True
+    )
+
+class StaticStylishPortletControlPanelAdapter(SchemaAdapterBase):
+    adapts(IPloneSiteRoot)
+    implements(IStaticStylishPortletPanelSchema)
+
+    def __init__(self, context):
+        super(StaticStylishPortletControlPanelAdapter, self).__init__(context)
+        self.context = context
+        self.pp = getToolByName(context, 'portal_properties', None)
+
+    def get_portlet_dropdown(self):
+        return  [ValueTitlePair(v,t) for (v,t) in getVocabulary(self.context)]
+
+    def set_portlet_dropdown(self, value):
+        dropdown_list = []
+        for vt in value:
+            value = vt.value
+            title = vt.title or value
+            dropdown_list.append('%s|%s' % (value, title))
+        self.setValue(dropdown_list)
+
+    portlet_dropdown = property(get_portlet_dropdown, set_portlet_dropdown)
+
+    def setValue(self, value):
+        if self.pp is not None:
+            if getattr(self.pp, 'staticportlet_properties', None) is None:
+                self.pp.addPropertySheet(
+                    'staticportlet_properties',
+                    'Static Stylish portlet properties'
+                )
+            sheet = getattr(self.pp, 'staticportlet_properties', None)
+            if not sheet.hasProperty('portlet_dropdown'):
+                sheet.manage_addProperty('portlet_dropdown', value, 'lines')
+            else:
+                sheet.manage_changeProperties(portlet_dropdown=value)
+
+valuetitle_widget = CustomWidgetFactory(ObjectWidget, ValueTitlePair)
+combination_widget = CustomWidgetFactory(ListSequenceWidget,
+                                         subwidget=valuetitle_widget)
+
+class StaticStylishPortletControlPanel(ControlPanelForm):
+
+    form_fields = form.FormFields(IStaticStylishPortletPanelSchema)
+    form_fields['portlet_dropdown'].custom_widget = combination_widget
+
+    label = _("Static Stylish portlet settings")
+    description = _("This form is for managing Static Stylish portlet "
+                     "classes available on portlet add/edit form.")
+    form_name = _("Static Stylish portlet settings")
+
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configure.zcml
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configure.zcml	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/browser/configure.zcml	(revision 616)
@@ -0,0 +1,17 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="quintagroup.portlet.static">
+
+  <adapter factory=".configlet.StaticStylishPortletControlPanelAdapter" />
+
+  <browser:page
+      name="staticstylishportlet-controlpanel"
+      for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+      class=".configlet.StaticStylishPortletControlPanel"
+      permission="cmf.ManagePortal"
+      />
+
+</configure>
+
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configlet.txt
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configlet.txt	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configlet.txt	(revision 616)
@@ -0,0 +1,144 @@
+Static Stylish portlet configlet
+================================
+
+Static Stylish portlet ships with it's own configuration page which you can
+access at:
+    ${your/portal/url}/@@staticstylishportlet-controlpanel
+
+or from Plone Control Panel under 'Add-on Product Configuration' section.
+
+
+Prepare testing environment
+---------------------------
+
+We use zope.testbrowser to simulate browser interaction in order to show
+the main flow of pages. This is not a true functional test, because we also
+inspect and modify the internal state of the ZODB, but it is a useful way of
+making sure we test the full end-to-end process of creating and modifying
+content.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> portal_url = self.portal.absolute_url()
+
+The following is useful when writing and debugging testbrowser tests. It lets
+us see error messages properly.
+
+    >>> browser.handleErrors = False
+    >>> self.portal.error_log._ignored_exceptions = ()
+
+We then turn off the various portlets, because they sometimes duplicate links
+and text (e.g. the navtree, the recent recent items listing) that we wish to
+test for in our own views. Having no portlets makes things easier.
+
+    >>> from zope.component import getUtility, getMultiAdapter
+    >>> from plone.portlets.interfaces import IPortletManager
+    >>> from plone.portlets.interfaces import IPortletAssignmentMapping
+
+    >>> left_column = getUtility(IPortletManager, name=u"plone.leftcolumn")
+    >>> left_assignable = getMultiAdapter((self.portal, left_column), IPortletAssignmentMapping)
+    >>> for name in left_assignable.keys():
+    ...     del left_assignable[name]
+
+    >>> right_column = getUtility(IPortletManager, name=u"plone.rightcolumn")
+    >>> right_assignable = getMultiAdapter((self.portal, right_column), IPortletAssignmentMapping)
+    >>> for name in right_assignable.keys():
+    ...     del right_assignable[name]
+
+
+Finally, we need to log in as the portal owner, i.e. an administrator user. We
+do this from the login page.
+
+    >>> from Products.PloneTestCase.setup import portal_owner, default_password
+    >>> browser.open(portal_url + '/login_form?came_from=' + portal_url)
+    >>> browser.getControl(name='__ac_name').value = portal_owner
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+
+
+Configlet Registration
+----------------------
+
+Firstly check whether configlet is really registered:
+
+    >>> from Products.CMFCore.utils import getToolByName
+    >>> cp = getToolByName(self.portal, 'portal_controlpanel')
+    >>> actions = [a.id for a in cp.listActions()]
+    >>> 'StaticStylishPortlet' in actions
+    True
+
+
+Access to configlet
+-------------------
+
+Let's see if we can go to /@@staticstylishportlet-controlpanel url.
+
+    >>> browser.open('%s/@@staticstylishportlet-controlpanel' % portal_url)
+
+Is there configlet title on the requested page?
+
+    >>> 'Static Stylish portlet settings' in browser.contents
+    True
+
+
+Configlet Validation Functionality
+----------------------------------
+
+Check whether validation is working properly. Set no value to new entry item.
+
+    >>> browser.getControl(name='form.portlet_dropdown.add').click()
+    >>> browser.getControl(name='form.portlet_dropdown.1.value').value = ''
+
+Now save form. We shoud obtain missing value error:
+
+    >>> browser.getControl(name='form.actions.save').click() 
+    >>> 'value: Required input is missing.' in browser.contents
+    True
+
+
+Configlet Save Functionality
+----------------------------
+
+It's time to correct previous error-prone situation. Set missing value.
+
+    >>> browser.getControl(name='form.portlet_dropdown.1.value').value = 'new_value'
+
+And submit form again. This time we should see 'Changes saved.' message:
+
+    >>> browser.getControl(name='form.actions.save').click() 
+    >>> 'Changes saved.' in browser.contents
+    True
+
+and value should be duplicated into title field since we left title input empty:
+
+    >>> browser.getControl(name='form.portlet_dropdown.1.title').value
+    'new_value'
+
+And finally check portal_properties to ensure our settings page did everything
+correctly on the back end:
+
+    >>> sheet = getToolByName(self.portal, 'portal_properties').staticportlet_properties
+    >>> 'new_value|new_value' in sheet.getProperty('portlet_dropdown')
+    True
+
+
+Configlet Cancel Functionality
+------------------------------
+
+The last thing we are going to check is configlet's Cancel button:
+
+    >>> browser.getControl(name='form.actions.cancel').click()
+    >>> 'Changes canceled.' in browser.contents
+    True
+
+    >>> browser.url.endswith('/plone_control_panel')
+    True
+
+As you can see Cancel button redirected us to Plone Control Panel.
+
+
+That's it.
+
+
+
+
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configure.zcml
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configure.zcml	(revision 615)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/configure.zcml	(revision 616)
@@ -10,4 +10,6 @@
 
     <i18n:registerTranslations directory="locales" />
+
+    <include package=".browser" />
 
     <genericsetup:registerProfile
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/controlpanel.xml
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/controlpanel.xml	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/controlpanel.xml	(revision 616)
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<object name="portal_controlpanel"
+        meta_type="Plone Control Panel Tool"
+        xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+        i18n:domain="quintagroup.portlet.static">
+ <configlet title="Static Stylish Portlet" action_id="StaticStylishPortlet"
+    appId="quintagroup.portlet.static" category="Products" condition_expr=""
+    url_expr="string:${portal_url}/@@staticstylishportlet-controlpanel"
+    visible="True" i18n:attributes="title">
+  <permission>Manage portal</permission>
+ </configlet>
+</object>
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/propertiestool.xml
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/propertiestool.xml	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/profiles/default/propertiestool.xml	(revision 616)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool">
+ <object name="staticportlet_properties" meta_type="Plone Property Sheet">
+  <property name="title">Static Stylish portlet properties</property>
+  <property name="portlet_dropdown" type="lines" purge="False">
+   <element value="portletStaticClassOne|Class One"/>
+  </property>
+ </object>
+</object>
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/staticstylishportlet.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/staticstylishportlet.py	(revision 615)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/staticstylishportlet.py	(revision 616)
@@ -10,4 +10,5 @@
 from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
 
+from quintagroup.portlet.static.utils import getVocabulary
 from quintagroup.portlet.static import StaticStylishPortletMessageFactory as _
 
@@ -22,5 +23,6 @@
 
     styling = schema.Choice(title=_(u"Portlet style"),
-                            description=_(u"Choose a css style for the porlet."),
+                            description=_(u"Choose a css style for the porlet. "
+                                          "You can manage these entries from the plone control panel."),
                             required=False,
                             default='',
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/tests/test_configlet.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/tests/test_configlet.py	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/tests/test_configlet.py	(revision 616)
@@ -0,0 +1,18 @@
+import unittest
+import doctest
+from Testing import ZopeTestCase as ztc
+
+from quintagroup.portlet.static.tests.base import FunctionalTestCase
+
+def test_suite():
+    return unittest.TestSuite([
+
+        ztc.ZopeDocFileSuite(
+            'configlet.txt', package='quintagroup.portlet.static',
+            test_class=FunctionalTestCase,
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE | doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
+
+     ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/utils.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/utils.py	(revision 616)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/utils.py	(revision 616)
@@ -0,0 +1,27 @@
+"""Some utility functions for common use"""
+
+from Products.CMFCore.utils import getToolByName
+
+def getVocabulary(context):
+    pp = getToolByName(context, 'portal_properties', None)
+    styles = None
+    if pp is not None:
+        sheet = getattr(pp, 'staticportlet_properties', None)
+        if sheet is not None:
+            dropdown_list = sheet.getProperty('portlet_dropdown', None)
+            if dropdown_list is not None:
+                styles = []
+                value_list = []
+                for line in dropdown_list:
+                    values = filter(lambda x:x.strip(), line.split('|', 1))
+                    if len(values) == 0:
+                        continue
+                    elif len(values) == 1:
+                        value = title = values[0]
+                    else:
+                        value = values[0]
+                        title = values[1]
+                    if value not in value_list:
+                        value_list.append(value)
+                        styles.append((value, title))
+    return styles
Index: intagroup.portlet.static/trunk/quintagroup/portlet/static/version.txt
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/version.txt	(revision 615)
+++ 	(revision )
@@ -1,1 +1,0 @@
-0.1
Index: /quintagroup.portlet.static/trunk/quintagroup/portlet/static/vocabularies.py
===================================================================
--- /quintagroup.portlet.static/trunk/quintagroup/portlet/static/vocabularies.py	(revision 615)
+++ /quintagroup.portlet.static/trunk/quintagroup/portlet/static/vocabularies.py	(revision 616)
@@ -3,10 +3,14 @@
 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 
+from Products.CMFCore.utils import getToolByName
+
+from quintagroup.portlet.static.utils import getVocabulary
 from quintagroup.portlet.static import StaticStylishPortletMessageFactory as _
 
-# Change the following default HTML class name with your own. Add more HTML classes to be available for you in Portlet style drop down menu 
 
+# fallback in case there is no portlet_dropdown lines property inside
+# staticporlet_properties property sheed in portal_properties tool
 PORTLET_CSS_STYLES = (
-    (u"portletStaticClassOne", _(u"Class One")),
+    (u"portletStaticClassOne", u"Class One"),
 )
 
@@ -15,6 +19,24 @@
 
     def __call__(self, context):
-        items = [SimpleTerm(value, value, title) for value, title in PORTLET_CSS_STYLES]
+        styles = getVocabulary(context)
+        if styles is None:
+            styles = PORTLET_CSS_STYLES
+        charset = self._charset(context)
+        items = []
+        for value, title in styles:
+            if not isinstance(title, unicode):
+                title = title.decode(charset)
+            if not isinstance(value, unicode):
+                value = value.decode(charset)
+            items.append(SimpleTerm(value, value, _(title)))
         return SimpleVocabulary(items)
 
+    def _charset(self, context):
+        pp = getToolByName(context, 'portal_properties', None)
+        if pp is not None:
+            site_properties = getattr(pp, 'site_properties', None)
+            if site_properties is not None:
+                return site_properties.getProperty('default_charset', 'utf-8')
+        return 'utf-8'
+
 PortletCSSVocabulary = PortletCSSVocabulary()
