Subversion Repositories Filer-Free

Rev

Rev 28 | Rev 30 | 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;
28 gdshaw@RISCPKG.ORG 42
        wblock.flags|=wimp_WINDOW_IGNORE_XEXTENT;
21 gdshaw@RISCPKG.ORG 43
        wblock.icon_count=0;
44
        create_window(wblock);
45
 
46
        // Resize extent to match actual visible area.
47
        wimp_window_state wstate;
48
        get_window_state(wstate);
49
        os_box extent;
50
        extent.x0=0;
51
        extent.y0=-(wstate.visible.y1-wstate.visible.y0);
52
        extent.x1=wstate.visible.x1-wstate.visible.x0;
53
        extent.y1=0;
54
        window::set_extent(extent);
55
 
25 gdshaw@RISCPKG.ORG 56
        // Open window, but keep it hidden from view.
21 gdshaw@RISCPKG.ORG 57
        wimp_window_info winfo;
58
        get_window_info_header(winfo);
59
        wimp_open open;
60
        open.visible.x0=winfo.visible.x0;
61
        open.visible.y0=winfo.visible.y1-(winfo.extent.y1-winfo.extent.y0);
62
        open.visible.x1=winfo.visible.x0+(winfo.extent.x1-winfo.extent.x0);
63
        open.visible.y1=winfo.visible.y1;
64
        open.visible=winfo.visible;
65
        open.xscroll=0;
66
        open.yscroll=0;
25 gdshaw@RISCPKG.ORG 67
        open.next=wimp_HIDDEN;
68
        open_window(open);
69
 
70
        // Reformat content of window.
71
        reformat();
72
 
73
        // Reopen window, now making it visible.
74
        get_window_state(wstate);
75
        open.visible=wstate.visible;
76
        open.xscroll=wstate.xscroll;
77
        open.yscroll=wstate.yscroll;
21 gdshaw@RISCPKG.ORG 78
        open.next=wimp_TOP;
79
        open_window(open);
80
}
81
 
82
filer_window::~filer_window()
83
{
84
        // Delete pathname buffer.
85
        delete[] _pathname;
86
}
87
 
88
void filer_window::handle_redraw_request(wimp_draw& block)
89
{
25 gdshaw@RISCPKG.ORG 90
        // Fetch layout.
91
        layout_method& layout=_options.layout();
92
        int xgap=layout.xgap();
93
        int ygap=layout.ygap();
94
 
21 gdshaw@RISCPKG.ORG 95
        int more=0;
96
        xwimp_redraw_window(&block,&more);
97
        while (more)
98
        {
25 gdshaw@RISCPKG.ORG 99
                // Get clipping coordinates with respect to this window.
100
                int xmin=block.clip.x0-block.box.x0+block.xscroll-xgap;
101
                int ymin=block.clip.y0-block.box.y1+block.yscroll+ygap;
102
                int xmax=block.clip.x1-block.box.x0+block.xscroll-xgap;
103
                int ymax=block.clip.y1-block.box.y1+block.yscroll+ygap;
104
 
105
                // Determine which cells are within clipping box.
106
                int xcmin=(xmin)/(_xcsize+xgap);
107
                int ycmin=(-ymax)/(_ycsize+ygap);
108
                int xcmax=(xmax-1)/(_xcsize+xgap)+1;
109
                int ycmax=(-ymin-1)/(_ycsize+ygap)+1;
110
                if (xcmin<0) xcmin=0;
111
                if (ycmin<0) ycmin=0;
112
                if (xcmax>_xccount) xcmax=_xccount;
113
                if (ycmax>_yccount) ycmax=_yccount;
114
 
115
                // Iterate over cells to be redrawn.
116
                for (int yc=ycmin;yc<ycmax;++yc)
117
                {
118
                        for (int xc=xcmin;xc<xcmax;++xc)
119
                        {
120
                                // Determine whether cell is occupied.
121
                                int i=xc+yc*_xccount;
122
                                if (i<static_cast<int>(_directory.size()))
123
                                {
124
                                        // Redraw cell.
125
                                        os_box box;
126
                                        box.x0=xc*(_xcsize+xgap)+xgap;
127
                                        box.y0=-yc*(_ycsize+ygap)-_ycsize-ygap;
128
                                        box.x1=box.x0+_xcsize;
129
                                        box.y1=box.y0+_ycsize;
130
                                        layout.plot(box,*_directory[i],
131
                                                _directory[i].selected(),_options);
132
                                }
133
                        }
134
                }
135
 
21 gdshaw@RISCPKG.ORG 136
                xwimp_get_rectangle(&block,&more);
137
        }
138
}
139
 
28 gdshaw@RISCPKG.ORG 140
void filer_window::handle_open_request(wimp_open& block)
141
{
142
        int xccount=_xccount;
143
        int yccount=_yccount;
144
        reformat(block.visible.x1-block.visible.x0);
145
        xwimp_open_window(&block);
146
        if (_xccount!=xccount||_yccount!=yccount) force_redraw();
147
}
148
 
29 gdshaw@RISCPKG.ORG 149
void filer_window::handle_close_request(wimp_close& block)
150
{
151
        wimp_pointer pointer;
152
        xwimp_get_pointer_info(&pointer);
153
 
154
        if (pointer.buttons&wimp_CLICK_ADJUST)
155
        {
156
                os_coord offset;
157
                offset.x=0;
158
                offset.y=0;
159
                open_parent(offset);
160
        }
161
 
162
        delete this;
163
}
164
 
21 gdshaw@RISCPKG.ORG 165
void filer_window::reload()
166
{
167
        static int buffer[256];
168
        _directory.load(_pathname,buffer,sizeof(buffer));
169
}
25 gdshaw@RISCPKG.ORG 170
 
171
void filer_window::reformat()
172
{
173
        wimp_window_state wstate;
174
        get_window_state(wstate);
175
        reformat(wstate.visible.x1-wstate.visible.x0);
176
}
177
 
178
void filer_window::reformat(int xsize)
179
{
180
        // Fetch layout.
181
        layout_method& layout=options().layout();
182
        int xgap=layout.xgap();
183
        int ygap=layout.ygap();
184
 
185
        // Calculate cell size.  This must be able to accommodate
186
        // - the minimum cell size for the chosen layout, and
187
        // - the actual size occupied by each file to be listed.
188
        os_coord csize=layout.min_size(_options);
189
        for (unsigned int i=0;i!=_directory.size();++i)
190
        {
191
                os_coord size=layout.size(*_directory[i],_options);
192
                if (size.x>csize.x) csize.x=size.x;
193
                if (size.y>csize.y) csize.y=size.y;
194
        }
195
 
196
        // Apply the calculated cell size.
197
        _xcsize=csize.x;
198
        _ycsize=csize.y;
199
 
200
        // Determine number of rows and columns.
201
        _xccount=xsize/(_xcsize+xgap);
202
        if (_xccount<1) _xccount=1;
203
        _yccount=(_directory.size()+_xccount-1)/_xccount;
204
        if (_yccount<1) _yccount=1;
205
 
206
        // Calculate new extent.
207
        int extent_xsize=_xccount*(_xcsize+xgap)+xgap;
208
        int extent_ysize=_yccount*(_ycsize+ygap)+ygap;
209
 
28 gdshaw@RISCPKG.ORG 210
        // Do not force the window to become narrower than the width requested,
25 gdshaw@RISCPKG.ORG 211
        // unless there are too few directory entries to justify that width.
212
        if (extent_xsize<xsize)
213
        {
214
                extent_xsize=xsize;
215
                if (((extent_xsize+_xcsize-1)/(_xcsize+xgap))>
216
                        static_cast<int>(_directory.size()))
217
                {
218
                        extent_xsize=_directory.size()*(_xcsize+xgap)+xgap;
219
                }
220
        }
221
 
222
        // Apply the calculated extent.
223
        os_box extent;
224
        extent.x0=0;
225
        extent.y0=-extent_ysize;
226
        extent.x1=extent_xsize;
227
        extent.y1=0;
228
        set_extent(extent);
229
}
29 gdshaw@RISCPKG.ORG 230
 
231
void filer_window::open_parent(const os_coord& offset) const
232
{
233
        // Determine whether there is a parent directory.
234
        char* lastdot=strrchr(_pathname,'.');
235
        if (lastdot&&strcmp(lastdot+1,"$"))
236
        {
237
                // Find top-left corner of this window.
238
                wimp_window_state state;
239
                get_window_state(state);
240
 
241
                // Add offset to give top-left corner of new window.
242
                os_box box;
243
                box.x0=state.visible.x0+offset.x;
244
                box.y1=state.visible.y1+offset.y;
245
                box.x1=box.x0;
246
                box.y0=box.y1;
247
 
248
                // Open new window.
249
                *lastdot=0;
250
                new filer_window((filer_application*)parent_application(),
251
                        _pathname,box,_options);
252
                *lastdot='.';
253
        }
254
}