Subversion Repositories Filer-Free

Rev

Rev 21 | Rev 28 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
21 gdshaw@RISCPKG.ORG 1
// This file is part of the free Filer module for RISC OS.
2
// Copyright  2007 Graham Shaw.
3
// Redistribution and modification are permitted under the terms of the
4
// GNU General Public License (version 2 or any later version).
5
 
6
#include <cstring>
7
 
8
#include "template_loader.h"
25 gdshaw@RISCPKG.ORG 9
#include "layout_method.h"
21 gdshaw@RISCPKG.ORG 10
#include "filer_window.h"
11
#include "filer_application.h"
12
 
13
filer_window::filer_window(filer_application* app,const char* pathname,
25 gdshaw@RISCPKG.ORG 14
        const os_box& box,const filer_options& options):
21 gdshaw@RISCPKG.ORG 15
        window(app),
16
        _pathname(new char[std::strlen(pathname)+1]),
25 gdshaw@RISCPKG.ORG 17
        _options(options),
18
        _directory(options.sort()),
19
        _xcsize(68),
20
        _ycsize(68),
21
        _xccount(1),
22
        _yccount(1)
21 gdshaw@RISCPKG.ORG 23
{
24
        // Copy pathname into buffer owned by this object.
25
        std::strcpy(_pathname,pathname);
26
 
27
        // Load directory listing.
28
        reload();
29
 
30
        // Create window from template.
31
        template_loader loader("directory","Resources:$.Resources.Filer.Templates");
32
        wimp_window& wblock=loader;
33
        wblock.title_flags|=wimp_ICON_INDIRECTED;
34
        wblock.title_data.indirected_text.text=_pathname;
35
        wblock.title_data.indirected_text.validation="";
36
        wblock.title_data.indirected_text.size=strlen(_pathname);
37
        wblock.visible=box;
38
        wblock.extent.x0=0;
39
        wblock.extent.y0=-(box.y1-box.y0);
40
        wblock.extent.x1=box.x1-box.x0;
41
        wblock.extent.y1=0;
42
        wblock.icon_count=0;
43
        create_window(wblock);
44
 
45
        // Resize extent to match actual visible area.
46
        wimp_window_state wstate;
47
        get_window_state(wstate);
48
        os_box extent;
49
        extent.x0=0;
50
        extent.y0=-(wstate.visible.y1-wstate.visible.y0);
51
        extent.x1=wstate.visible.x1-wstate.visible.x0;
52
        extent.y1=0;
53
        window::set_extent(extent);
54
 
25 gdshaw@RISCPKG.ORG 55
        // Open window, but keep it hidden from view.
21 gdshaw@RISCPKG.ORG 56
        wimp_window_info winfo;
57
        get_window_info_header(winfo);
58
        wimp_open open;
59
        open.visible.x0=winfo.visible.x0;
60
        open.visible.y0=winfo.visible.y1-(winfo.extent.y1-winfo.extent.y0);
61
        open.visible.x1=winfo.visible.x0+(winfo.extent.x1-winfo.extent.x0);
62
        open.visible.y1=winfo.visible.y1;
63
        open.visible=winfo.visible;
64
        open.xscroll=0;
65
        open.yscroll=0;
25 gdshaw@RISCPKG.ORG 66
        open.next=wimp_HIDDEN;
67
        open_window(open);
68
 
69
        // Reformat content of window.
70
        reformat();
71
 
72
        // Reopen window, now making it visible.
73
        get_window_state(wstate);
74
        open.visible=wstate.visible;
75
        open.xscroll=wstate.xscroll;
76
        open.yscroll=wstate.yscroll;
21 gdshaw@RISCPKG.ORG 77
        open.next=wimp_TOP;
78
        open_window(open);
79
}
80
 
81
filer_window::~filer_window()
82
{
83
        // Delete pathname buffer.
84
        delete[] _pathname;
85
}
86
 
87
void filer_window::handle_redraw_request(wimp_draw& block)
88
{
25 gdshaw@RISCPKG.ORG 89
        // Fetch layout.
90
        layout_method& layout=_options.layout();
91
        int xgap=layout.xgap();
92
        int ygap=layout.ygap();
93
 
21 gdshaw@RISCPKG.ORG 94
        int more=0;
95
        xwimp_redraw_window(&block,&more);
96
        while (more)
97
        {
25 gdshaw@RISCPKG.ORG 98
                // Get clipping coordinates with respect to this window.
99
                int xmin=block.clip.x0-block.box.x0+block.xscroll-xgap;
100
                int ymin=block.clip.y0-block.box.y1+block.yscroll+ygap;
101
                int xmax=block.clip.x1-block.box.x0+block.xscroll-xgap;
102
                int ymax=block.clip.y1-block.box.y1+block.yscroll+ygap;
103
 
104
                // Determine which cells are within clipping box.
105
                int xcmin=(xmin)/(_xcsize+xgap);
106
                int ycmin=(-ymax)/(_ycsize+ygap);
107
                int xcmax=(xmax-1)/(_xcsize+xgap)+1;
108
                int ycmax=(-ymin-1)/(_ycsize+ygap)+1;
109
                if (xcmin<0) xcmin=0;
110
                if (ycmin<0) ycmin=0;
111
                if (xcmax>_xccount) xcmax=_xccount;
112
                if (ycmax>_yccount) ycmax=_yccount;
113
 
114
                // Iterate over cells to be redrawn.
115
                for (int yc=ycmin;yc<ycmax;++yc)
116
                {
117
                        for (int xc=xcmin;xc<xcmax;++xc)
118
                        {
119
                                // Determine whether cell is occupied.
120
                                int i=xc+yc*_xccount;
121
                                if (i<static_cast<int>(_directory.size()))
122
                                {
123
                                        // Redraw cell.
124
                                        os_box box;
125
                                        box.x0=xc*(_xcsize+xgap)+xgap;
126
                                        box.y0=-yc*(_ycsize+ygap)-_ycsize-ygap;
127
                                        box.x1=box.x0+_xcsize;
128
                                        box.y1=box.y0+_ycsize;
129
                                        layout.plot(box,*_directory[i],
130
                                                _directory[i].selected(),_options);
131
                                }
132
                        }
133
                }
134
 
21 gdshaw@RISCPKG.ORG 135
                xwimp_get_rectangle(&block,&more);
136
        }
137
}
138
 
139
void filer_window::reload()
140
{
141
        static int buffer[256];
142
        _directory.load(_pathname,buffer,sizeof(buffer));
143
}
25 gdshaw@RISCPKG.ORG 144
 
145
void filer_window::reformat()
146
{
147
        wimp_window_state wstate;
148
        get_window_state(wstate);
149
        reformat(wstate.visible.x1-wstate.visible.x0);
150
}
151
 
152
void filer_window::reformat(int xsize)
153
{
154
        // Fetch layout.
155
        layout_method& layout=options().layout();
156
        int xgap=layout.xgap();
157
        int ygap=layout.ygap();
158
 
159
        // Calculate cell size.  This must be able to accommodate
160
        // - the minimum cell size for the chosen layout, and
161
        // - the actual size occupied by each file to be listed.
162
        os_coord csize=layout.min_size(_options);
163
        for (unsigned int i=0;i!=_directory.size();++i)
164
        {
165
                os_coord size=layout.size(*_directory[i],_options);
166
                if (size.x>csize.x) csize.x=size.x;
167
                if (size.y>csize.y) csize.y=size.y;
168
        }
169
 
170
        // Apply the calculated cell size.
171
        _xcsize=csize.x;
172
        _ycsize=csize.y;
173
 
174
        // Determine number of rows and columns.
175
        _xccount=xsize/(_xcsize+xgap);
176
        if (_xccount<1) _xccount=1;
177
        _yccount=(_directory.size()+_xccount-1)/_xccount;
178
        if (_yccount<1) _yccount=1;
179
 
180
        // Calculate new extent.
181
        int extent_xsize=_xccount*(_xcsize+xgap)+xgap;
182
        int extent_ysize=_yccount*(_ycsize+ygap)+ygap;
183
 
184
        // Do not force the window to become narrower than it was previously,
185
        // unless there are too few directory entries to justify that width.
186
        if (extent_xsize<xsize)
187
        {
188
                extent_xsize=xsize;
189
                if (((extent_xsize+_xcsize-1)/(_xcsize+xgap))>
190
                        static_cast<int>(_directory.size()))
191
                {
192
                        extent_xsize=_directory.size()*(_xcsize+xgap)+xgap;
193
                }
194
        }
195
 
196
        // Apply the calculated extent.
197
        os_box extent;
198
        extent.x0=0;
199
        extent.y0=-extent_ysize;
200
        extent.x1=extent_xsize;
201
        extent.y1=0;
202
        set_extent(extent);
203
}