Project

General

Profile

Patch #1864 » themes.rb

Patch to automatically extend /public with javascripts and images from a theme folder. - Chris Hart, 2008-09-05 20:55

 
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
# 
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
# 
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

    
18
module Redmine
19
  module Themes
20
  
21
    # Return an array of installed themes
22
    def self.themes
23
      @@installed_themes ||= scan_themes
24
    end
25
    
26
    # Rescan themes directory
27
    def self.rescan
28
      @@installed_themes = scan_themes
29
    end
30
    
31
    # Return theme for given id, or nil if it's not found
32
    def self.theme(id)
33
      themes.find {|t| t.id == id}
34
    end
35
  
36
    # Class used to represent a theme
37
    class Theme
38
      attr_reader :name, :dir, :stylesheets, :images, :javascripts
39
      
40
      def initialize(path)
41
        @dir = File.basename(path)
42
        @name = @dir.humanize
43
        @stylesheets = Dir.glob("#{path}/stylesheets/*.css").collect {|f| File.basename(f).gsub(/\.css$/, '')}
44
        @javascripts = Dir.glob("#{path}/javascripts/*.js").collect {|f| File.basename(f).gsub(/\.js$/, '')}
45
        @images      = Dir.glob("#{path}/images/*.*").collect {|f| File.basename(f)}
46
      end
47
      
48
      # Directory name used as the theme id
49
      def id; dir end
50

    
51
      def <=>(theme)
52
        name <=> theme.name
53
      end
54
    end
55
    
56
    private
57
        
58
    def self.scan_themes
59
      dirs = Dir.glob("#{RAILS_ROOT}/public/themes/*").select do |f|
60
        # A theme should at least override application.css
61
        File.directory?(f) && File.exist?("#{f}/stylesheets/application.css")
62
      end
63
      dirs.collect {|dir| Theme.new(dir)}.sort
64
    end
65
  end
66
end
67

    
68
module ApplicationHelper
69
  def stylesheet_path(source)
70
    @current_theme ||= Redmine::Themes.theme(Setting.ui_theme)
71
    super((@current_theme && @current_theme.stylesheets.include?(source)) ?
72
      "/themes/#{@current_theme.dir}/stylesheets/#{source}" : source)
73
  end
74
  
75
  def path_to_stylesheet(source)
76
    stylesheet_path source
77
  end
78

    
79
  def image_path(source)
80
    @current_theme ||= Redmine::Themes.theme(Setting.ui_theme)
81
    super((@current_theme && @current_theme.images.include?(source)) ?
82
      "/themes/#{@current_theme.dir}/images/#{source}" : source)
83
  end
84
  
85
  def path_to_image(source)
86
    image_path source    
87
  end
88
  
89
  def javascript_path(source)
90
    @current_theme ||= Redmine::Themes.theme(Setting.ui_theme)
91
    super((@current_theme && @current_theme.javascripts.include?(source)) ?
92
      "/themes/#{@current_theme.dir}/javascripts/#{source}" : source)
93
  end
94
  
95
  def path_to_javascript(source)
96
    javascript_path source
97
  end
98
  
99
  # or if we wanted to 'catch all' and allow the theme to have it's own version of anything in public
100
  # we could have just have compute_public_path look in the theme first
101
  # def compute_public_path(source, dir, ext = nil, include_host = true)
102
  # end
103
  
104
end
(1-1/2)