Subversion Repositories Filer-Free

Rev

Rev 25 | Rev 29 | 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
 
21 gdshaw@RISCPKG.ORG 149
void filer_window::reload()
150
{
151
        static int buffer[256];
152
        _directory.load(_pathname,buffer,sizeof(buffer));
153
}
25 gdshaw@RISCPKG.ORG 154
 
155
void filer_window::reformat()
156
{
157
        wimp_window_state wstate;
158
        get_window_state(wstate);
159
        reformat(wstate.visible.x1-wstate.visible.x0);
160
}
161
 
162
void filer_window::reformat(int xsize)
163
{
164
        // Fetch layout.
165
        layout_method& layout=options().layout();
166
        int xgap=layout.xgap();
167
        int ygap=layout.ygap();
168
 
169
        // Calculate cell size.  This must be able to accommodate
170
        // - the minimum cell size for the chosen layout, and
171
        // - the actual size occupied by each file to be listed.
172
        os_coord csize=layout.min_size(_options);
173
        for (unsigned int i=0;i!=_directory.size();++i)
174
        {
175
                os_coord size=layout.size(*_directory[i],_options);
176
                if (size.x>csize.x) csize.x=size.x;
177
                if (size.y>csize.y) csize.y=size.y;
178
        }
179
 
180
        // Apply the calculated cell size.
181
        _xcsize=csize.x;
182
        _ycsize=csize.y;
183
 
184
        // Determine number of rows and columns.
185
        _xccount=xsize/(_xcsize+xgap);
186
        if (_xccount<1) _xccount=1;
187
        _yccount=(_directory.size()+_xccount-1)/_xccount;
188
        if (_yccount<1) _yccount=1;
189
 
190
        // Calculate new extent.
191
        int extent_xsize=_xccount*(_xcsize+xgap)+xgap;
192
        int extent_ysize=_yccount*(_ycsize+ygap)+ygap;
193
 
28 gdshaw@RISCPKG.ORG 194
        // Do not force the window to become narrower than the width requested,
25 gdshaw@RISCPKG.ORG 195
        // unless there are too few directory entries to justify that width.
196
        if (extent_xsize<xsize)
197
        {
198
                extent_xsize=xsize;
199
                if (((extent_xsize+_xcsize-1)/(_xcsize+xgap))>
200
                        static_cast<int>(_directory.size()))
201
                {
202
                        extent_xsize=_directory.size()*(_xcsize+xgap)+xgap;
203
                }
204
        }
205
 
206
        // Apply the calculated extent.
207
        os_box extent;
208
        extent.x0=0;
209
        extent.y0=-extent_ysize;
210
        extent.x1=extent_xsize;
211
        extent.y1=0;
212
        set_extent(extent);
213
}